最近工做中我都是基於註解實現AOP功能,經常使用的開啓AOP的註解是@EnableAspectJAutoProxy,咱們就從它入手。
上面的動圖的流程的步驟就是:
@EnableAspectJAutoProxy
--> AspectJAutoProxyRegistrar
-->AopConfigUtils .registerAspectJAnnotationAutoProxyCreatorIfNecessary
-->AnnotationAwareAspectJAutoProxyCreator.classjava
AnnotationAwareAspectJAutoProxyCreator查看其中文註釋(以下),肯定它就是AOP的核心類!--溫安適 20191020spring
/** 1.AspectJAwareAdvisorAutoProxyCreator的子類 ,用於處理當前應用上下文中的註解切面 2.任何被AspectJ註解的類將自動被識別。 3.若SpringAOP代理模式能夠識別,優先使用Spring代理模式。 4.它覆蓋了方法執行鏈接點 5.若是使用<aop:include>元素, 則只有名稱與include模式匹配的@aspectj bean才被視爲切面 ,並由spring自動代理。 6. Spring Advisors的處理請查閱, org.springframework.aop .framework.autoproxy.AbstractAdvisorAutoProxyCreator */ @SuppressWarnings("serial") public class AnnotationAwareAspectJAutoProxyCreator extends AspectJAwareAdvisorAutoProxyCreator { //...省略實現 }註解切面
雖然找到了核心類,可是並無找到核心方法!下面咱們嘗試畫類圖肯定核心方法。緩存
AnnotationAwareAspectJAutoProxyCreator的部分類圖。
從類圖看到了AnnotationAwareAspectJAutoProxyCreator實現了BeanPostProcessor,而AOP功能應該在建立完Bean以後執行,猜想AnnotationAwareAspectJAutoProxyCreator實現BeanPostProcessor的postProcessAfterInitialization(實例化bean後處理)是核心方法。 查看AnnotationAwareAspectJAutoProxyCreator實現的postProcessAfterInitialization方法,實際該方法在其父類AbstractAutoProxyCreator中。ide
//AbstractAutoProxyCreator中的postProcessAfterInitialization實現 @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { if (bean != null) { Object cacheKey = getCacheKey(bean.getClass(), beanName); if (!this.earlyProxyReferences.contains(cacheKey)) { return wrapIfNecessary(bean, beanName, cacheKey); } } return bean; }
發現發現疑似方法wrapIfNecessary,查看其源碼以下,發現createProxy方法。肯定找對了地方。post
protected Object wrapIfNecessary (Object bean, String beanName, Object cacheKey) { if (beanName != null && this.targetSourcedBeans.contains(beanName)) { return bean; } if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) { return bean; } if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) { this.advisedBeans.put(cacheKey, Boolean.FALSE); return bean; } // 建立代理 Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null); if (specificInterceptors != DO_NOT_PROXY) { this.advisedBeans.put(cacheKey, Boolean.TRUE); Object proxy = createProxy( bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean)); this.proxyTypes.put(cacheKey, proxy.getClass()); return proxy; } this.advisedBeans.put(cacheKey, Boolean.FALSE); return bean; }
即AnnotationAwareAspectJAutoProxyCreator實現BeanPostProcessor的postProcessAfterInitialization方法,在該方法中由wrapIfNecessary實現了AOP的功能。 wrapIfNecessary中有2個和核心方法ui
查看源碼以下,默認實如今AbstractAdvisorAutoProxyCreator中。this
@Override @Nullable protected Object[] getAdvicesAndAdvisorsForBean( Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) { List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName); if (advisors.isEmpty()) { return DO_NOT_PROXY; } return advisors.toArray(); }
查閱findEligibleAdvisors方法,就幹了3件事spa
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) { //找全部加強器 List<Advisor> candidateAdvisors = findCandidateAdvisors(); //找全部匹配的加強器 List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName); extendAdvisors(eligibleAdvisors); if (!eligibleAdvisors.isEmpty()) { //排序 eligibleAdvisors = sortAdvisors(eligibleAdvisors); } return eligibleAdvisors; }
AnnotationAwareAspectJAutoProxyCreator 重寫了findCandidateAdvisors,下面咱們看看具體實現了什麼.net
@Override protected List<Advisor> findCandidateAdvisors() { // Add all the Spring advisors found according to superclass rules. List<Advisor> advisors = super.findCandidateAdvisors(); // Build Advisors for all AspectJ aspects in the bean factory. if (this.aspectJAdvisorsBuilder != null) { //@Aspect註解的類在這裏除了 advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors()); } return advisors; }
從該方法咱們能夠看到處理@Aspect註解的bean的方法是:this.aspectJAdvisorsBuilder.buildAspectJAdvisors()。 這個方法以下:代理
public List<Advisor> buildAspectJAdvisors() { List<String> aspectNames = this.aspectBeanNames; if (aspectNames == null) { synchronized (this) { aspectNames = this.aspectBeanNames; if (aspectNames == null) { List<Advisor> advisors = new ArrayList<>(); aspectNames = new ArrayList<>(); //找到全部BeanName String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors( this.beanFactory, Object.class, true, false); for (String beanName : beanNames) { if (!isEligibleBean(beanName)) { continue; } // 必須注意,bean會提早暴露,並被Spring容器緩存,可是這時還不能織入。 Class<?> beanType = this.beanFactory.getType(beanName); if (beanType == null) { continue; } if (this.advisorFactory.isAspect(beanType)) { //找到全部被@Aspect註解的類 aspectNames.add(beanName); AspectMetadata amd = new AspectMetadata(beanType, beanName); if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) { MetadataAwareAspectInstanceFactory factory = new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName); //解析封裝爲Advisor返回 List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory); if (this.beanFactory.isSingleton(beanName)) { this.advisorsCache.put(beanName, classAdvisors); } else { this.aspectFactoryCache.put(beanName, factory); } advisors.addAll(classAdvisors); } else { // Per target or per this. if (this.beanFactory.isSingleton(beanName)) { throw new IllegalArgumentException("Bean with name '" + beanName + "' is a singleton, but aspect instantiation model is not singleton"); } MetadataAwareAspectInstanceFactory factory = new PrototypeAspectInstanceFactory(this.beanFactory, beanName); this.aspectFactoryCache.put(beanName, factory); advisors.addAll(this.advisorFactory.getAdvisors(factory)); } } } this.aspectBeanNames = aspectNames; return advisors; } } } if (aspectNames.isEmpty()) { return Collections.emptyList(); } List<Advisor> advisors = new ArrayList<>(); for (String aspectName : aspectNames) { List<Advisor> cachedAdvisors = this.advisorsCache.get(aspectName); if (cachedAdvisors != null) { advisors.addAll(cachedAdvisors); } else { MetadataAwareAspectInstanceFactory factory = this.aspectFactoryCache.get(aspectName); advisors.addAll(this.advisorFactory.getAdvisors(factory)); } } return advisors; }
這個方法能夠歸納爲:
衆所周知,建立代理的經常使用的2種方式是:JDK建立和CGLIB,下面咱們就看看這2中建立代理的例子。
import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; public class JDKProxyMain { public static void main(String[] args) { JDKProxyTestInterface target = new JDKProxyTestInterfaceImpl(); // 根據目標對象建立代理對象 JDKProxyTestInterface proxy = (JDKProxyTestInterface) Proxy .newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), new JDKProxyTestInvocationHandler(target)); // 調用代理對象方法 proxy.testProxy(); } interface JDKProxyTestInterface { void testProxy(); } static class JDKProxyTestInterfaceImpl implements JDKProxyTestInterface { @Override public void testProxy() { System.out.println("testProxy"); } } static class JDKProxyTestInvocationHandler implements InvocationHandler { private Object target; public JDKProxyTestInvocationHandler(Object target){ this.target=target; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("執行前"); Object result= method.invoke(this.target,args); System.out.println("執行後"); return result; } }
import org.springframework.cglib.proxy.Enhancer; import org.springframework.cglib.proxy.MethodInterceptor; import org.springframework.cglib.proxy.MethodProxy; import java.lang.reflect.Method; public class CglibProxyTest { static class CglibProxyService { public CglibProxyService(){ } void sayHello(){ System.out.println(" hello !"); } } static class CglibProxyInterceptor implements MethodInterceptor{ @Override public Object intercept(Object sub, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { System.out.println("before hello"); Object object = methodProxy.invokeSuper(sub, objects); System.out.println("after hello"); return object; } } public static void main(String[] args) { // 經過CGLIB動態代理獲取代理對象的過程 Enhancer enhancer = new Enhancer(); // 設置enhancer對象的父類 enhancer.setSuperclass(CglibProxyService.class); // 設置enhancer的回調對象 enhancer.setCallback(new CglibProxyInterceptor()); // 建立代理對象 CglibProxyService proxy= (CglibProxyService)enhancer.create(); System.out.println(CglibProxyService.class); System.out.println(proxy.getClass()); // 經過代理對象調用目標方法 proxy.sayHello(); } }
類型 | jdk建立動態代理 | cglib建立動態代理 |
---|---|---|
原理 | java動態代理是利用反射機制生成一個實現代理接口的匿名類,在調用具體方法前調用InvokeHandler來處理 | cglib動態代理是利用asm開源包,對代理對象類的class文件加載進來,經過修改其字節碼生成子類來處理 |
核心類 | Proxy 建立代理利用反射機制生成一個實現代理接口的匿名類InvocationHandler 方法攔截器接口,須要實現invoke方法 | net.sf.cglib.proxy.Enhancer:主要加強類,經過字節碼技術動態建立委託類的子類實例net.sf.cglib.proxy.MethodInterceptor:方法攔截器接口,須要實現intercept方法 |
侷限性 | 只能代理實現了接口的類 | 不能對final修飾的類進行代理,也不能處理final修飾的方法 |
Spring的選擇選擇如何代理時在DefaultAopProxyFactory 中。
public class DefaultAopProxyFactory implements AopProxyFactory, Serializable { @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); } } //... }
//exposeProxy=true AopContext 能夠訪問,proxyTargetClass=true CGLIB生成代理 @EnableAspectJAutoProxy(exposeProxy=true,proxyTargetClass=true)
總結下Spring如何選擇建立代理的方式:
Spring如何實現AOP?,您能夠這樣說: