本文参照《架构探险》一书。html
aop 无非是在原有的方法先后加入自定义的代码。整体思想:java
JDK动态代理只能对实现了接口的类生成代理,而不能针对类 。 CGLIB是针对类实现代理,主要是对指定的类生成一个子类,覆盖其中的方法 。 由于是继承,因此该类或方法最好不要声明成final ,final能够阻止继承和多态。架构
<aop:aspectj-autoproxy proxy-target-class="true"/> 强制使用cglib作动态代理框架
public class AopHelper { ... static { try { //从容器中找到代理类和被代理类的关系 Map<Class<?>, Set<Class<?>>> proxyMap = createProxyMap(); Map<Class<?>, List<Proxy>> targetMap = createTargetMap(proxyMap); for (Map.Entry<Class<?>, List<Proxy>> targetEntry : targetMap.entrySet()) { //1.建立代理类 Object proxy = ProxyManager.createProxy(targetEntry.getKey(), targetEntry.getValue()); //2.将容器中的class 换为 代理类 BeanHelper.setBean(targetEntry.getKey(), proxy); } } catch (Exception e) { LOGGER.error("aop fail",e); } } ... }
@Aspect(Controller.class) public class ControllerAspect extends AspectProxy
extends AspectProxy 实现父类方法,也就是咱们要添加的操做。jvm
@Aspect(Controller.class) 表示这个代理类代理的是哪一个类(具体方法代理规则能够在代理类方法中判断,作不一样处理)ide
/** * class集合中找到指定切面的集合 * @param aspect * @return * @throws Exception */ private static Set<Class<?>> createTargetClassSet(Aspect aspect) throws Exception { Set<Class<?>> targetClassSet = new HashSet<Class<?>>(); Class<? extends Annotation> annotation = aspect.value(); if (annotation != null && !annotation.equals(Aspect.class)) { targetClassSet.addAll(ClassHelper.getClassSetByAnnotation(annotation)); } return targetClassSet; } /** * 找到继承AspectProxy的代理类 * 根据代理类的Aspect注解中value 找到被代理类 * 返回代理类和被代理类的映射 * proxyClass -> set<targetClass> * @return * @throws Exception */ private static Map<Class<?>, Set<Class<?>>> createProxyMap() throws Exception { Map<Class<?>, Set<Class<?>>> proxyMap = new HashMap<>(); //切面类 Set<Class<?>> proxyClassSet = ClassHelper.getClassSetBySuper(AspectProxy.class); for (Class<?> proxyCls : proxyClassSet) { if (proxyCls.isAnnotationPresent(Aspect.class)){//继承了AspectProxy而且被Aspect标注 Aspect aspect = proxyCls.getAnnotation(Aspect.class); Set<Class<?>> targetClassSet = createTargetClassSet(aspect); proxyMap.put(proxyCls, targetClassSet); } } //添加事务代理 addTransactionProxy(proxyMap); return proxyMap; } private static void addTransactionProxy(Map<Class<?>, Set<Class<?>>> proxyMap) { Set<Class<?>> serviceClassSet = ClassHelper.getClassSetByAnnotation(Service.class); proxyMap.put(TransactionProxy.class, serviceClassSet); } /** * targetClass -> List<proxy instance> * @param proxyMap * @return * @throws Exception */ private static Map<Class<?>, List<Proxy>> createTargetMap(Map<Class<?>, Set<Class<?>>> proxyMap) throws Exception { HashMap<Class<?>, List<Proxy>> targetMap = new HashMap<>(); for (Map.Entry<Class<?>, Set<Class<?>>> proxyEntry : proxyMap.entrySet()) { Class<?> proxyClass = proxyEntry.getKey(); Set<Class<?>> targetClassSet = proxyEntry.getValue(); for (Class<?> targetClass : targetClassSet) { Proxy proxy = (Proxy) proxyClass.newInstance(); if (targetMap.containsKey(targetClass)) { targetMap.get(targetClass).add(proxy); } else { List<Proxy> proxyList = new ArrayList<>(); proxyList.add(proxy); targetMap.put(targetClass, proxyList); } } } return targetMap; }
//cglib 建立代理对象 public class ProxyManager { public static <T> T createProxy(final Class<T> targetClass, final List<Proxy> proxyList) { //CGLib提供建立代理对象,代理对象是一个代理链 return (T) Enhancer.create(targetClass, new MethodInterceptor() { @Override public Object intercept(Object targetObject, Method targetMethod, Object[] methodParams, MethodProxy methodProxy) throws Throwable { //返回代理对象 代理链 的结果 return new ProxyChain(targetClass, targetObject, targetMethod, methodProxy, methodParams, proxyList).doProxyChain(); } }); } }
代理对象是ProxyChain类型,由于同一个class可能有多个aop须要处理,因此是一条链。this
public class ProxyChain { private final Class<?> targetClass; private final Object targetObject; private final Method targetMethod; private final MethodProxy methodProxy; private final Object[] methodParams; ... public Object doProxyChain() throws Throwable { Object methodResult; if (proxyIndex < proxyList.size()) { methodResult = proxyList.get(proxyIndex++).doProxy(this); } else { //最后执行目标对象的业务逻辑 //方法代理,参数只传入哪一个对象,什么参数 methodResult = methodProxy.invokeSuper(targetObject, methodParams); } return methodResult; } }
public abstract class AspectProxy implements Proxy{ private static final Logger LOGGER = LoggerFactory.getLogger(AspectProxy.class); @Override public Object doProxy(ProxyChain proxyChain) throws Throwable { Object result = null; Class<?> targetClass = proxyChain.getTargetClass(); Object[] methodParams = proxyChain.getMethodParams(); Method targetMethod = proxyChain.getTargetMethod(); begin(); try { if (intercept(targetClass, targetMethod, methodParams)) { before(targetClass, targetMethod, methodParams); result = proxyChain.doProxyChain(); after(targetClass, targetMethod, methodParams, result); } else { result = proxyChain.doProxyChain(); } } catch (Exception e) { LOGGER.error("proxy fail",e); error(targetClass, targetMethod, methodParams, e); throw e; } finally { end(); } return result; } private void begin() { } public boolean intercept(Class<?> cls, Method method, Object[] params) { return true; } public void before(Class<?> cls, Method method, Object[] params) { } public void after(Class<?> cls, Method method, Object[] params, Object result) { } public void error(Class<?> cls, Method method, Object[] params, Throwable e) { } public void end() {} }
public class TransactionProxy implements Proxy { //保证同一线程中事务控制相关逻辑只会执行一次? private static final ThreadLocal<Boolean> FLAG_HOLDER = new ThreadLocal<Boolean>(){ protected Boolean initialValue() { return false; } }; @Override public Object doProxy(ProxyChain proxyChain) throws Exception, Throwable { Boolean flag = FLAG_HOLDER.get(); Method method = proxyChain.getTargetMethod(); Object result = null; if (!flag && method.isAnnotationPresent(Transaction.class)) { FLAG_HOLDER.set(true); try { DatabaseHelper.beginTransaction(); LOGGER.debug("begin transaction"); result = proxyChain.doProxyChain(); DatabaseHelper.commitTransaction(); LOGGER.debug("commit transaction"); } catch (Exception e) { DatabaseHelper.rollbackTransaction(); LOGGER.debug("rollback transaction"); throw e; } finally { //DatabaseHelper.closeConnetion(); FLAG_HOLDER.remove(); } } else { result = proxyChain.doProxyChain(); } return result; } }
FLAG_HOLDER应该是防止事务的嵌套,好比两个service都标注了@transaction,一个serviceA一个ServiceB, 可是ServiceA中又调用了ServiceB,这样没有FLAG_HOLDER就会先启动A的事务,再启动B的事务(A的事务还没完)。加上FLAG_HOLDER就只会启动A的事务,B看到已经有事务在执行就不启动事务,默认加入了A的事务。.net