içinde JDK ve CGLIB proxy'lerinin karıştırılması Yay ile çalışan bir uygulamam var ve bazı yerlerde AOP kullanıyorum. @ Transactional notunu arayüz seviyesinde kullanmak istediğim için, Spring'in JDK proxy'leri oluşturmasına izin vermeliyim. Bu nedenle, proxy-target-class özelliğini true değerine ayarlamıyorum. Öte yandan, tavsiye ettiğim her sınıf için bir arayüz oluşturmak istemiyorum: eğer arayüz sadece bir anlam ifade etmiyorsa, sadece uygulama yapmak istiyorum ve Spring bir CGLIB proxy'si yaratmalıdır.Bahar
Açıkladığım gibi her şey mükemmel çalışıyordu. Ancak, arayüzler halinde girme ve uygulama sınıfları tarafından "miras alınan" gibi "miras alma" gibi bazı ek açıklamaların (benim tarafımdan yaratılmış) olmasını istedim. İlkbaharda AOP için yerleşik destek ile bunu yapamayacağımı ortaya koyuyor (en azından bazı araştırmalardan sonra nasıl yapılacağını anlayamadım. Arayüzdeki ek açıklama uygulama sınıfında görünmüyor ve dolayısıyla bu sınıf tavsiye edilmez).
yüzden diğer yöntem ek açıklamaları arayüzleri gitmek için izin kendi pointcut ve önleme uygulamaya karar verdik. Temel olarak, pointcut, metot üzerindeki açıklamalara ve sınıf veya üst sınıfların uyguladığı arayüzlerin aynı metotta (aynı isim ve parametre tipleri) bulunana kadar bakmaya çalışmaktadır.Sorun şu ki: DefaultAdvisorAutoProxyCreator çekirdeği bildirdiğimde, bu nokta/engelleyiciyi düzgün bir şekilde uygulayacağınız zaman, arabirimler olmadan sınıflar hakkında bilgi verme davranışı bozulur. Görünüşe göre bir şeyler ters gidiyor ve Spring bir kez CGLIB ve daha sonra da JDK ile iki kez dersimi proxy yapmaya çalışıyor.
@Component
public class ServiceExecutorImpl
{
@Transactional
public Object execute(...)
{
...
}
}
Diğer bazı fasulye autowire deneyin:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:task="http://www.springframework.org/schema/task"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.0.xsd">
<!-- Activates various annotations to be detected in bean classes: Spring's
@Required and @Autowired, as well as JSR 250's @Resource. -->
<context:annotation-config />
<context:component-scan base-package="mypackage" />
<!-- Instruct Spring to perform declarative transaction management automatically
on annotated classes. -->
<tx:annotation-driven transaction-manager="transactionManager" />
<bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator" />
<bean id="logger.advisor" class="org.springframework.aop.support.DefaultPointcutAdvisor">
<constructor-arg>
<bean class="mypackage.MethodAnnotationPointcut">
<constructor-arg value="mypackage.Trace" />
</bean>
</constructor-arg>
<constructor-arg>
<bean class="mypackage.TraceInterceptor" />
</constructor-arg>
</bean>
</beans>
Bu, hiçbir arayüzlerle ben proxy uygulanacak istiyorum sınıfıdır:
Bu
benim yapılandırma dosyasıdır gibi:public class BaseService {
@Autowired
private ServiceExecutorImpl serviceExecutorImpl;
...
}
Aşağıdaki özel durumu elde ediyorum:
java.lang.IllegalArgumentException: Can not set mypackage.ServiceExecutorImpl field mypackage.BaseService.serviceExecutor to $Proxy26
Bu
Bahar çıkışının bazı satırlar şunlardır:13:51:12,672 [main] DEBUG [org.springframework.aop.framework.Cglib2AopProxy] - Creating CGLIB2 proxy: target source is SingletonTargetSource for target object [[email protected]]
...
13:51:12,782 [main] DEBUG [org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator] - Creating implicit proxy for bean 'serviceExecutorImpl' with 0 common interceptors and 1 specific interceptors
13:51:12,783 [main] DEBUG [org.springframework.aop.framework.JdkDynamicAopProxy] - Creating JDK dynamic proxy: target source is SingletonTargetSource for target object [[email protected]]
birisi yardımcı olacaktır düşünürse ben tam çıkış kaynağı olabilir. Spring'in neden sınıfımı "çifte-proxy" yapmaya çalıştığı konusunda hiçbir fikrim yok ve neden DefaultAdvisorAutoProxyCreator fasulyesini bildirdiğimde böyle oluyor.
Şimdi bir süredir bununla mücadele ediyorum ve herhangi bir yardım veya fikir çok takdir edilecektir.
DÜZENLEME: Bu benim önleme kaynak kodu, istenen şekilde
. Temel olarak yöntem yürütme işlemini günlüğe kaydeder (yalnızca @Trace ile kesişen yöntemler kesilir). Yöntem @Trace (false) ile açıklanmışsa, yöntem döndürene kadar günlük kaydı askıya alınır.
public class TraceInterceptor
implements
MethodInterceptor
{
@Override
public Object invoke(
MethodInvocation invocation)
throws Throwable
{
if(ThreadExecutionContext.getCurrentContext().isLogSuspended()) {
return invocation.proceed();
}
Method method = AopUtils.getMostSpecificMethod(invocation.getMethod(),
invocation.getThis().getClass());
Trace traceAnnotation = method.getAnnotation(Trace.class);
if(traceAnnotation != null && traceAnnotation.value() == false) {
ThreadExecutionContext.getCurrentContext().suspendLogging();
Object result = invocation.proceed();
ThreadExecutionContext.getCurrentContext().resumeLogging();
return result;
}
ThreadExecutionContext.startNestedLevel();
SimpleDateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy - HH:mm:ss.SSS");
Logger.log("Timestamp: " + dateFormat.format(new Date()));
String toString = invocation.getThis().toString();
Logger.log("Class: " + toString.substring(0, toString.lastIndexOf('@')));
Logger.log("Method: " + getMethodName(method));
Logger.log("Parameters: ");
for(Object arg : invocation.getArguments()) {
Logger.log(arg);
}
long before = System.currentTimeMillis();
try {
Object result = invocation.proceed();
Logger.log("Return: ");
Logger.log(result);
return result;
} finally {
long after = System.currentTimeMillis();
Logger.log("Total execution time (ms): " + (after - before));
ThreadExecutionContext.endNestedLevel();
}
}
// Just formats a method name, with parameter and return types
private String getMethodName(
Method method)
{
StringBuffer methodName = new StringBuffer(method.getReturnType().getSimpleName() + " "
+ method.getName() + "(");
Class<?>[] parameterTypes = method.getParameterTypes();
if(parameterTypes.length == 0) {
methodName.append(")");
} else {
int index;
for(index = 0; index < (parameterTypes.length - 1); index++) {
methodName.append(parameterTypes[ index ].getSimpleName() + ", ");
}
methodName.append(parameterTypes[ index ].getSimpleName() + ")");
}
return methodName.toString();
}
}
Evet, sanırım CGLIB proxy'leri bazı arabirimleri uygular. Ama bence bu benim kontrolüm dışında değil mi? Yazdığım orijinal sınıf herhangi bir arabirimi uygulamıyor, hatta herhangi bir sınıfı genişletmiyor (elbette Nesne hariç). Tavsiye Edilsin diye kontrol etmem bana yardımcı olabilir, çünkü bu sınıf Spring tarafından tavsiye ediliyor (@ Transactional nedeniyle) ve yazdığım herhangi bir nokta ile değil. Bana yardım edip edemeyeceğini görmek için adresine bir göz atacağım. Teşekkürler! –
önleme kodunu gösterebilir misin? – Bozho
Sorumu engelleyicinin kaynağıyla düzenledim. Bir ipucu? –