当动态代理遇到ioc
在 work log 2020.4.28中,我们使用jdk动态代理处理方法的事务增强
图1 问题的引出

根本原因:动态代理和cglib,会丢掉被代理类成员变量和方法上的注解
起先,我们禁止被增强的类里面使用注解注入依赖,代码会自动审核这种情况
private static final class TransactionProxyProvider<T> implements Provider<T> {
private Object target;
public TransactionProxyProvider(Object target) {
this.target = target;
}
@Override
public T get() {
try {
// Class cl = target.getClass();
// Field [] fields = cl.getDeclaredFields();
// for(Field field : fields) {
// field.setAccessible(true);
// if(field.isAnnotationPresent(Inject.class))
// throw new RuntimeException("proxy class do not allow com.google.inject annotation - " + cl.getName());
// }
return (T)new TransactionProxyFactory(target).getProxyInstance();
} catch (Exception e) {
loggerCommon.error(e.getMessage(), e);
}
return null;
}
}
实用性太差,放弃
后来有了图2 解决方案,有点像:结合自定义注解的 spring 动态注入中UserServic自动装配到UserController中,UserService是带@Service类,UserController是动态注入的类,手动将工厂中UserService实例装配到UserController 的userService对象上

设计用例:
本文中,分三步走
1 设原始类A,代理类APlus对A进行JDK动态代理,通过@Bean(spring)或Provider(guice)手动注入类到factory
2 其它环境中的类会依赖A,以@Autowired(spring)或@Inject(guice)修饰
2 A本身依赖的类在private对象(设b)上,由于A没有注入,注入的是其代理类APlus,故A上的以@Autowired(spring)或@Inject(guice)修饰的依赖不会自动装配,我们手动将工厂中相应类型的实例set上去,运行期查看b是否为null
work log 中有1 2 3详细代码
JDK动态代理代码:
public class TransactionProxyFactory implements InvocationHandler {
private Object target;
public TransactionProxyFactory(Object target){
this.target = target;
}
// private <T> T getBeanFromFactoryGuice(Class<T> c) {
// Injector injector = CRFGuiceContext.getInjector();
// return injector.getInstance(c);
// }
//
// private Class getBeanInjectAnnotationGuice() {
// return com.google.inject.Inject.class;
// }
private <T> T getBeanFromFactorySpring(Class<T> c) {
return (T)SpringContextUtil.getBean(c);
}
private Class getBeanInjectAnnotationSpring() {
return org.springframework.beans.factory.annotation.Autowired.class;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Class clProxy = target.getClass();
Field[] fields = clProxy.getDeclaredFields();
for(Field field : fields) {
field.setAccessible(true);
if(!field.isAnnotationPresent(getBeanInjectAnnotationSpring()))
continue;
String name = field.getName();
Class fieldType = field.getType();
Object obj = getBeanFromFactorySpring(fieldType);
if(obj != null)
field.set(target, obj);
}
SCEF_DB_TRANSACTIONAL scef_db_transactional = method.getAnnotation(SCEF_DB_TRANSACTIONAL.class);
if(scef_db_transactional != null) {
ScefOrmSession scefOrmSession = getBeanFromFactorySpring(ScefOrmSession.class);
Boolean readOnly = scef_db_transactional.readOnly();
int isolation = scef_db_transactional.isolation();
try {
scefOrmSession.startTransaction(readOnly, isolation);
Object returnValue = method.invoke(target, args);
scefOrmSession.commit();
return returnValue;
} catch (InvocationTargetException ie) {
Throwable throwable = ie.getTargetException();
Class c1 = throwable.getClass();
Class [] c2 = scef_db_transactional.noRollbackFor();
int sum = 0;
for(Class c : c2) {
if(c.equals(c1))
sum ++ ;
}
if(sum == 0)
scefOrmSession.rollback();
else
scefOrmSession.commit();
throw new DBException(throwable);
} catch (Exception e) {
throw new DBException(e);
} finally {
scefOrmSession.endTransaction();
}
} else {
Object returnValue = method.invoke(target, args);
return returnValue;
}
}
//给目标对象生成代理对象
public Object getProxyInstance(){
return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
}
}
浙公网安备 33010602011771号