Ne istediğiniz için kutudan çıkmış AspectJ çözümü yoktur, çünkü herhangi bir nesnenin yöntem yürütmelerini engellerseniz, bu nesnelere işaret eden açıklamalı alanlarla bağlantı yoktur. Açıklamalı sınıfların veya açıklamalı yöntemlerin yöntem yürütmelerini engellemek daha kolay olurdu, ancak bu yapmak istediğiniz şey değil. Gördüğünüz gibi, benim yönü önemli" bir dizi tutar
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Retention(RetentionPolicy.RUNTIME)
public @interface Important {}
public class Counter {
private int count = 0;
public void add(int value) {
count = count + value;
}
@Override
public String toString() {
return super.toString() + "[count=" + count + "]";
}
}
public class Visitors {
@Important
Counter counter = new Counter();
public void increaseCounter() {
counter.add(1);
}
public static void main(String[] args) {
Visitors visitors = new Visitors();
visitors.increaseCounter();
visitors.counter.add(3);
System.out.println("visitors.counter = " + visitors.counter);
System.out.println("--------------------");
Counter unimportantCounter = new Counter();
unimportantCounter.add(11);
unimportantCounter.add(22);
System.out.println("unimportantCounter = " + unimportantCounter);
System.out.println("--------------------");
unimportantCounter = visitors.counter;
unimportantCounter.add(5);
System.out.println("visitors.counter = " + visitors.counter);
System.out.println("unimportantCounter = " + unimportantCounter);
System.out.println("--------------------");
visitors.counter = new Counter();
visitors.increaseCounter();
visitors.counter.add(3);
unimportantCounter.add(100);
System.out.println("visitors.counter = " + visitors.counter);
System.out.println("unimportantCounter = " + unimportantCounter);
System.out.println("--------------------");
Visitors otherVisitors = new Visitors();
otherVisitors.increaseCounter();
otherVisitors.counter.add(50);
System.out.println("otherVisitors.counter = " + otherVisitors.counter);
System.out.println("--------------------");
otherVisitors.counter = visitors.counter;
System.out.println("visitors.counter = " + visitors.counter);
System.out.println("otherVisitors.counter = " + otherVisitors.counter);
System.out.println("--------------------");
otherVisitors.counter = new Counter();
visitors.increaseCounter();
otherVisitors.increaseCounter();
System.out.println("visitors.counter = " + visitors.counter);
System.out.println("otherVisitors.counter = " + otherVisitors.counter);
}
}
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.aspectj.lang.Signature;
import org.aspectj.lang.SoftException;
public aspect ImportantMethodInterceptor {
Map<Object, Set<Object>> importantObjects = new HashMap<Object, Set<Object>>();
pointcut importantSetter(Object newValue, Object target) :
set(@Important * *) && args(newValue) && target(target);
pointcut unimportantSetter(Object newValue, Object target) :
!set(@Important * *) && set(* *) && !withincode(*.new(..)) && args(newValue) && target(target);
pointcut publicMethod(Object target) :
execution(public * *(..)) && target(target) && !execution(public String *..toString());
before(Object newValue, Object target) : importantSetter(newValue, target) {
Object oldValue = getFieldValue(thisJoinPoint.getSignature(), target);
System.out.println("Important object for target " + target + ": " + oldValue + " -> " + newValue);
synchronized (importantObjects) {
Set<Object> referrers;
if (oldValue != null) {
referrers = importantObjects.get(oldValue);
if (referrers != null) {
referrers.remove(target);
if (referrers.size() == 0)
importantObjects.remove(oldValue);
}
}
if (newValue != null) {
referrers = importantObjects.get(newValue);
if (referrers == null) {
referrers = new HashSet<Object>();
importantObjects.put(newValue, referrers);
}
referrers.add(target);
}
}
}
// before(Object newValue, Object target) : unimportantSetter(newValue, target) {
// Object oldValue = getFieldValue(thisJoinPoint.getSignature(), target);
// System.out.println("Unimportant object for target " + target + ": " + oldValue + " -> " + newValue);
// }
before(Object target) : publicMethod(target) {
synchronized (importantObjects) {
if (importantObjects.get(target) != null)
System.out.println("Important method on " + target + ": " + thisJoinPointStaticPart);
else
System.out.println("Unimportant method on " + target + ": " + thisJoinPointStaticPart);
}
}
private Object getFieldValue(Signature signature, Object target) {
try {
Field field = signature.getDeclaringType().getDeclaredField(signature.getName());
field.setAccessible(true);
return field.get(target);
}
catch (Exception e) { throw new SoftException(e); }
}
}
: Burada
ayrıca sınırlamalar size geçici bir çözüm gösterir biraz kod örneği olmakla nesneleri". Daha doğrusu, anahtarların "önemli nesneler" olduğu ve değerlerin yönlendirme kümesi olduğu
Map
'dur. Bu gereklidir çünkü teorik olarak birkaç yönlendirici (ör.
Visitors
nesneleri) aynı "önemli nesnelere" işaret edebilir (örneğin, belirli bir
Counter
). Basit bir kümede "önemli nesneleri" kaydettiğimde örnek kodumun önceki bir sürümünde, daha önce hiç başvurulmadıklarında veya her zaman bunları bile kaldırarak bile daha önce "önemli nesneleri" daha önce kaldırma seçeneğini seçtim ikinci bir yönlendirici hala "önemli bir nesneyi" işaret ediyorduysa. Harita yaklaşımı, "önemli nesne" başına birden fazla yönlendirici kaydetmemi sağlıyor. Eğer
Visitors.main(String[])
çalıştırırsanız
yaptığında (çıktıyı daha bakın log istiyorsanız before ... : unimportantSetter ...
tavsiye yorumsuz lütfen) şu çıktıyı göreceksiniz:
Important object for target [email protected]: null -> [email protected][count=0]
Unimportant method on [email protected]: execution(void Visitors.increaseCounter())
Important method on [email protected][count=0]: execution(void Counter.add(int))
Important method on [email protected][count=1]: execution(void Counter.add(int))
visitors.counter = [email protected][count=4]
--------------------
Unimportant method on [email protected][count=0]: execution(void Counter.add(int))
Unimportant method on [email protected][count=11]: execution(void Counter.add(int))
unimportantCounter = [email protected][count=33]
--------------------
Important method on [email protected][count=4]: execution(void Counter.add(int))
visitors.counter = [email protected][count=9]
unimportantCounter = [email protected][count=9]
--------------------
Important object for target [email protected]: [email protected][count=9] -> [email protected][count=0]
Unimportant method on [email protected]: execution(void Visitors.increaseCounter())
Important method on [email protected][count=0]: execution(void Counter.add(int))
Important method on [email protected][count=1]: execution(void Counter.add(int))
Unimportant method on [email protected][count=9]: execution(void Counter.add(int))
visitors.counter = [email protected][count=4]
unimportantCounter = [email protected][count=109]
--------------------
Important object for target [email protected]: null -> [email protected][count=0]
Unimportant method on [email protected]: execution(void Visitors.increaseCounter())
Important method on [email protected][count=0]: execution(void Counter.add(int))
Important method on [email protected][count=1]: execution(void Counter.add(int))
otherVisitors.counter = [email protected][count=51]
--------------------
Important object for target [email protected]: [email protected][count=51] -> [email protected][count=4]
visitors.counter = [email protected][count=4]
otherVisitors.counter = [email protected][count=4]
--------------------
Important object for target [email protected]: [email protected][count=4] -> [email protected][count=0]
Unimportant method on [email protected]: execution(void Visitors.increaseCounter())
Important method on [email protected][count=4]: execution(void Counter.add(int))
Unimportant method on [email protected]: execution(void Visitors.increaseCounter())
Important method on [email protected][count=0]: execution(void Counter.add(int))
visitors.counter = [email protected][count=5]
otherVisitors.counter = [email protected][count=1]
dikkatlice günlük çıkışına main
kodu karşılaştırmak Lütfen hangi düzenli ve özel durumları test ettiğimi görmek için.
- Ben önemli alanlar
int
gibi ilkel türleri vardır ya teorik olarak "önemli nesneleri" olarak birden çok kez ortaya çıkabilir String
ler ise ne olacağı test etmedim: Dediğim gibi
, yaklaşım sınırlamaları vardır çünkü ilgisiz birkaç önemli üye eşit nesneler yaratır. Ayrıca otomatik (un) boksla ilgili ne olduğunu test etmedim, lütfen kendiniz deneyin. Görünüm kodu bir şekilde karmaşıktır ve muhtemelen şaşırtıcı derecede hızlı değildir.
- Henüz düşünmediğim başka sorunların olmayacağını garanti edemem.
Ancak, sınır koşullarını ve kullanım durumlarını kontrol ediyorsanız, ihtiyacınız olanı elde etmek için bilinçli bir karar verebilir ve kodu olduğu gibi kullanabilirsiniz. Kod muhtemelen iyileştirme potansiyeline sahip, sadece merak ettim ve bir konsept kanıtı kırmak istedim.
Şüphelendiğimi onayladığınız için, kullanıma hazır AJ ile istediğimi yapmak mümkün değil. AJ için çok yeni olmama rağmen, POC'nizde ne yapmaya çalıştığınızı görebiliyorum. Çok ilginç ve eğitici! Teşekkür ederiz! – JustOneMoreQuestion