Spring AOP源碼解析
阿新 • • 發佈:2018-05-06
spingaop sping aop 實現原理 源碼解析 以編程的方式使用spring提供的AOP功能,下面是一個簡單的例子:
package com.zws.spring.core.aop.springAop; import java.lang.reflect.Method; import org.springframework.aop.MethodBeforeAdvice; import org.springframework.aop.framework.ProxyFactory; public class SpringProxyClient { public static void main(String[] args) { ProxyFactory proxy = new ProxyFactory(new SpringPojo()); proxy.addAdvice(new PojoAdvice()); SpringPojo proxyPojo = (SpringPojo) proxy.getProxy(); proxyPojo.foo(); } } class SpringPojo { public void foo() { System.out.println("This is SpringPojo foo"); } } class PojoAdvice implements MethodBeforeAdvice{ @Override public void before(Method method, Object[] args, Object target) throws Throwable { System.out.println("This is bar"); } }
這段代碼最重要的一個類是ProxyFactory,此類以及相關的類的類圖如下:
如果想要使用AspectJ風格的AOP可以使用AspectJProxyFactory。在使用ProxyFactory生成代理對象的時候,當實例化ProxyFactory對象時就會收集代理目標對象的接口信息,源代碼如下:
public ProxyFactory(Object target) { setTarget(target); setInterfaces(ClassUtils.getAllInterfaces(target)); }
代理目標的接口信息存放在類AdvisedSupport的interfaces屬性中,此屬性是一個集合,如下:
private List<Class<?>> interfaces = new ArrayList<Class<?>>();
當然在實例化ProxyFactory對象之前Spring還會實例化一個更重要的對象:AopProxy對象,此接口才是真正產生代理對象的接口。父類ProxyCreatorSupport會保存一個AopProxyFactory類型的屬性aopProxyFactory,如下:
private AopProxyFactory aopProxyFactory;
此屬性會在ProxyCreatorSupport的無參構造函數中實例化,如下:
/** * Create a new ProxyCreatorSupport instance. */ public ProxyCreatorSupport() { this.aopProxyFactory = new DefaultAopProxyFactory(); }
當調用ProxyFactory的getProxy()方法時首先會調用DefaultAopProxyFactory類的createAopProxy()方法產生一個AopProxy對象,此時就需要判斷使用JDK的動態代理還是GCLIB的代理類產生代理對象,在條件允許的情況下Spring會首選JDK動態代理的方式,其判斷邏輯為目標對象類型是接口或者其本身就已經是一個JDK動態代理生成的對象。如果不滿足上面的條件就使用Cglib代理生成代理對象,其源碼如下:
@Override public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException { if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) { Class<?> targetClass = config.getTargetClass(); if (targetClass == null) { throw new AopConfigException("TargetSource cannot determine target class: " + "Either an interface or a target is required for proxy creation."); } if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) { return new JdkDynamicAopProxy(config); } return new ObjenesisCglibAopProxy(config); } else { return new JdkDynamicAopProxy(config); } }
AopProxy對象生成後就可以直接調用其getProxy()方法產生代理對象了。AopProxyFactory接口的createAopProxy()方法屏蔽了如何選擇以及選擇哪種代理,對客戶端而言這些都是透明的。
Spring AOP源碼解析