AOP(面向切面編程)在Spring中是被廣泛應用的(例如日志,事務,權限等),而它的基本原理便是動態代理。
我們知道動態代理有兩種:基於JDK的動態代理以及基於CGlib動態代理。以下是兩種動態代理的實現方式:

1 //JDK動態代理 2 public class JDKProxy implements InvocationHandler { 3 4 private Object object;// 被代理人 5 6 //這里的目標類型為Object,則可以接受任意一種參數作為被代理類,實現了動態代理。但是要注意下面的newProxyInstance()中的參數 7 public Object getInstance(Object object) { 8 this.object = object; 9 //與cglib的區別在於這里構建代理對象的時候需要傳入被代理對象的接口對象,第二個參數。而cglib不需要被代理對象實現任何接口即可 10 return Proxy.newProxyInstance(object.getClass().getClassLoader(), object.getClass().getInterfaces(), this); 11 } 12 13 //代理對象真正調用的方法 14 @Override 15 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 16 System.out.println("doSomething---------start"); 17 method.invoke(object, args); 18 System.out.println("doSomething---------end"); 19 return null; 20 } 21 22 } 23 24 //CGlib動態代理 25 public class CglibProxy implements MethodInterceptor { 26 private Object targetObject; 27 28 // 這里的目標類型為Object,則可以接受任意一種參數作為被代理類,實現了動態代理 29 public Object getInstance(Object target) { 30 this.targetObject = target; 31 Enhancer enhancer = new Enhancer(); 32 enhancer.setSuperclass(target.getClass()); 33 enhancer.setCallback(this); 34 //注意該處代理的創建過程 35 Object proxyObj = enhancer.create(); 36 return proxyObj;// 返回代理對象 37 } 38 39 //代理對象真正調用的方法 40 @Override 41 public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable { 42 Object obj = null; 43 System.out.println("doSomething---------start"); 44 obj = method.invoke(targetObject, args); 45 System.out.println("doSomething---------end"); 46 return obj; 47 } 48 49 }
具體兩種動態代理的差異在網上有很多各個方面的比較,在這里我就不再贅述。下面我再說說在Spring 5.0.3.RELEASE中實現AOP的原理(我的github中也有詳細的源碼注釋)。
在注解版的Spring AOP當中我們會有如下的代碼配置,其中@EnableAspectJAutoProxy便是開啟AOP支持的關鍵。
1 @EnableAspectJAutoProxy //開啟基於注解的AOP模式 2 @Configuration 3 @ComponentScan(value = {"com.aop"}) 4 public class AnnotationAopConfig { 5 6 @Bean("student") 7 public Student getStudent() { //把我們普通的Java Bean定義出來交給IOC容器管理 8 return new Student(); 9 } 10 11 @Bean 12 public LogAspect getLogAspect() { //定義切面類 13 return new LogAspect(); 14 } 15 }
我們跟蹤一下@EnableAspectJAutoProxy的源碼來看看它的定義,會發現它利用@Import導入了AspectJAutoProxyRegistrar.class組件:代碼塊一
由AspectJAutoProxyRegistrar.Class的定義可知其實現了ImportBeanDefinitionRegistrar接口,所以在IOC容器初始化的時候會調用該類的registerBeanDefinitions方法。通過觀察該方法實現,我們可以看到一行關鍵的代碼AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);:代碼塊二
這行代碼中所需要注冊的到底是什么東西呢?我們進一步一探究竟。在持續跟入代碼的過程中我們可以找到這么一塊代碼:return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);:代碼塊三
觀察源碼可以得知,該方法會將AnnotationAwareAspectJAutoProxyCreator類封裝為一個RootBeanDefinition然后添加到BeanDefinition的注冊類當中以AUTO_PROXY_CREATOR_BEAN_NAME。我們也可以找到關於AUTO_PROXY_CREATOR_BEAN_NAME的定義:代碼塊四
我們再分析一下AnnotationAwareAspectJAutoProxyCreator.Class的源碼,看看此類到底有何特別之處。觀察源碼我們可以發現AnnotationAwareAspectJAutoProxyCreator是BeanPostPrcsessor的子類:代碼塊五
1 /**********************代碼塊一***********************/ 2 3 @Target(ElementType.TYPE) 4 @Retention(RetentionPolicy.RUNTIME) 5 @Documented 6 @Import(AspectJAutoProxyRegistrar.class) //導入AspectJAutoProxyRegistrar組件 7 public @interface EnableAspectJAutoProxy { 8 /**********************代碼塊二***********************/ 9 class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar { 10 11 @Override 12 public void registerBeanDefinitions( 13 AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { 14 15 AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry); //如果需要的話注冊AspectJAnnotationAutoProxy 16 /**********************代碼塊三***********************/ 17 @Nullable 18 public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry, 19 @Nullable Object source) { 20 21 return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source); 22 } 23 /**********************代碼塊四***********************/ 24 /** 25 * The bean name of the internally managed auto-proxy creator. 26 */ 27 public static final String AUTO_PROXY_CREATOR_BEAN_NAME = "org.springframework.aop.config.internalAutoProxyCreator"; 28 private static BeanDefinition registerOrEscalateApcAsRequired(Class<?> cls, BeanDefinitionRegistry registry, 29 @Nullable Object source) { 30 31 Assert.notNull(registry, "BeanDefinitionRegistry must not be null"); 32 33 if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) { 34 BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME); 35 if (!cls.getName().equals(apcDefinition.getBeanClassName())) { 36 int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName()); 37 int requiredPriority = findPriorityForClass(cls); 38 if (currentPriority < requiredPriority) { 39 apcDefinition.setBeanClassName(cls.getName()); 40 } 41 } 42 return null; 43 } 44 45 RootBeanDefinition beanDefinition = new RootBeanDefinition(cls); 46 beanDefinition.setSource(source); 47 beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE); 48 beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); 49 registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);//注冊 50 return beanDefinition; 51 } 52 /**********************代碼塊五***********************/ 53 AnnotationAwareAspectJAutoProxyCreator 54 AnnotationAwareAspectJAutoProxyCreator 55 extends AspectJAwareAdvisorAutoProxyCreator 56 extends AbstractAdvisorAutoProxyCreator 57 extends AbstractAutoProxyCreator 58 extends ProxyProcessorSupport implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware 59 extends ...InstantiationAwareBeanPostProcessor Ordered 60 extends BeanPostProcessor
從以上代碼,我們可以知道@EnableAspectJAutoProxy大概做了這么一件事:將AnnotationAwareAspectJAutoProxyCreator.Class以名為“org.springframework.aop.config.internalAutoProxyCreator”的方式完成注冊BeanDefinition的操作。
然后我們再看看這塊內容對Spring容器啟動過程的影響。
我們以下面的代碼為入口進行分析:代碼塊一
我們進入IOC容器初始化過程看看對於進行了切面操作的類來說經歷了哪些操作,通過斷點我們可以跟蹤到此代碼處:PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this);這里是實例化各種BeanPostProcessor,並將其實例存放在BeanFactory當中:代碼塊二(當中代碼我挑出重要的部分。更加詳細的Spring源碼說明,請關注我的github)。
注冊了BeanPostProcessor的實例,我們看看普通Bean對象的創建。跟蹤源碼可知:通過finishBeanFactoryInitialization等一系列方法的調用到getBean(beanName);方法之中,在getBean(beanName);后續的調用之中又經過了查詢緩存,實例化依賴等一系列操作來到了createBean這個方法當中,我們可以通過代碼詳細分析其處理。我們可以找到Object beanInstance = doCreateBean(beanName, mbdToUse, args); 獲取Bean實例的地方。 再跟進去看它的實現:代碼塊三
我們現在觀察doCreateBean(beanName, mbdToUse, args); 源碼,其中實現了移除緩存、創建實例、初始化實例等一系列操作,其中在exposedObject = initializeBean(beanName, exposedObject, mbd);中變有我們需要的關鍵信息。:代碼塊四
initializeBean(beanName, exposedObject, mbd);這個方法里面有applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);和applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);兩個方法的調用。這里面的原理是獲取所有的beanPostProcessors遍歷調用其postProcessBeforeInitialization和postProcessAfterInitialization方法。這里我就不過多的贅述了。調試代碼我們可以發現后續的調用鏈如下AbstractAutoProxyCreator#postProcessAfterInitialization-->AbstractAutoProxyCreator#wrapIfNecessary。在這里我們就可以判斷其是否擁有增強器來創建代理對象,我們可以通過下面代碼來觀察其邏輯(增強器便是代理對象的各個方法封裝起來的對象):代碼塊五
進入代理構建入口Object proxy = createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));以下便是通過默認的GClib來進行對象的一個封裝。其代理封裝的對象如下:代碼塊六
1 /**********************代碼塊一***********************/ 2 @Test 3 public void test3() { 4 AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AnnotationAopConfig.class); //初始化IOC容器 5 String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames(); 6 7 Student student = (Student) applicationContext.getBean("student");//從容器中獲取對象 8 student.innerMethod(); //進行方法調用 9 applicationContext.close(); 10 } 11 /**********************代碼塊二***********************/ 12 public static void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) { 13 /** 14 * IOC:stepA6-1 獲取到所有已經定義了的,需要創建實例的所有實現BeanPostProcessor的類 15 * org.springframework.context.annotation.internalAutowiredAnnotationProcessor 16 * org.springframework.context.annotation.internalRequiredAnnotationProcessor 17 * org.springframework.aop.config.internalAutoProxyCreator 18 */ 19 String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false); 20 .... 21 /** 22 * 分離實現了PriorityOrdered、Ordered和rest接口的BeanPostProcessors 23 * 按順序注冊BeanPostProcessors 24 */ 25 List<String> orderedPostProcessorNames = new ArrayList<>(); 26 List<String> nonOrderedPostProcessorNames = new ArrayList<>(); 27 for (String ppName : postProcessorNames) { 28 if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) { //如果是PriorityOrdered的子類 29 .... 30 } 31 else if (beanFactory.isTypeMatch(ppName, Ordered.class)) { //AOP 匹配internalAutoProxyCreator,添加到orderedPostProcessorNames集合當中 32 orderedPostProcessorNames.add(ppName); 33 } 34 else { 35 nonOrderedPostProcessorNames.add(ppName); 36 } 37 } 38 // 首先, 注冊實現PriorityOrdered接口的BeanPostProcessors 39 sortPostProcessors(priorityOrderedPostProcessors, beanFactory); 40 registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors); 41 // Next, register the BeanPostProcessors that implement Ordered. 42 List<BeanPostProcessor> orderedPostProcessors = new ArrayList<>(); 43 for (String ppName : orderedPostProcessorNames) { 44 BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class); //實例化internalAutoProxyCreator 45 orderedPostProcessors.add(pp); 46 if (pp instanceof MergedBeanDefinitionPostProcessor) { 47 internalPostProcessors.add(pp);//將internalAutoProxyCreator實例放進去 48 } 49 } 50 sortPostProcessors(orderedPostProcessors, beanFactory); 51 registerBeanPostProcessors(beanFactory, orderedPostProcessors); //將BeanPostProcessor注冊到BeanFactory 52 .... 53 } 54 /**********************代碼塊三***********************/ 55 56 protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) 57 throws BeanCreationException { 58 .... 59 60 try { 61 // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance. 62 //IOC:stepA10 給BeanPostProcessor一個機會返回一個代理實例代替Bean實例 63 Object bean = resolveBeforeInstantiation(beanName, mbdToUse); 64 if (bean != null) { 65 return bean; 66 } 67 } 68 catch (Throwable ex) { 69 throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName, 70 "BeanPostProcessor before instantiation of bean failed", ex); 71 } 72 73 try { 74 Object beanInstance = doCreateBean(beanName, mbdToUse, args); //創建Bean實例 75 if (logger.isDebugEnabled()) { 76 logger.debug("Finished creating instance of bean '" + beanName + "'"); 77 } 78 return beanInstance; 79 } 80 catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) { 81 .... 82 } 83 } 84 /**********************代碼塊四***********************/ 85 protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args) 86 throws BeanCreationException { 87 // Instantiate the bean. 88 BeanWrapper instanceWrapper = null; 89 if (mbd.isSingleton()) { //如果是單例,從factoryBean實例緩存中移除 90 instanceWrapper = this.factoryBeanInstanceCache.remove(beanName); 91 } 92 if (instanceWrapper == null) { 93 instanceWrapper = createBeanInstance(beanName, mbd, args);//創建實例 94 } 95 .... 96 //緩存bean解決循環引用 97 .... 98 // Initialize the bean instance. 99 //初始化bean實例 100 Object exposedObject = bean; 101 try { 102 populateBean(beanName, mbd, instanceWrapper); //為Bean的屬性賦值 103 exposedObject = initializeBean(beanName, exposedObject, mbd); //初始化對象 104 } 105 .... 106 } 107 /**********************代碼塊五***********************/ 108 protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) { 109 if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) { 110 return bean; 111 } 112 if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) { 113 return bean; 114 } 115 if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) { 116 this.advisedBeans.put(cacheKey, Boolean.FALSE); 117 return bean; 118 } 119 120 // Create proxy if we have advice. 121 //如果有增強器的話就創建代理 122 Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null); 123 if (specificInterceptors != DO_NOT_PROXY) { 124 this.advisedBeans.put(cacheKey, Boolean.TRUE); 125 Object proxy = createProxy( 126 bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));//創建AOP代理對象 127 this.proxyTypes.put(cacheKey, proxy.getClass()); 128 return proxy; 129 } 130 131 this.advisedBeans.put(cacheKey, Boolean.FALSE); 132 return bean; 133 } 134 /**********************代碼塊六***********************/ 135 private static class DynamicAdvisedInterceptor implements MethodInterceptor, Serializable { 136 137 private final AdvisedSupport advised; 138 139 public DynamicAdvisedInterceptor(AdvisedSupport advised) { 140 this.advised = advised; 141 } 142 143 @Override 144 @Nullable 145 public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable { 146 Object oldProxy = null; 147 boolean setProxyContext = false; 148 Object target = null; 149 TargetSource targetSource = this.advised.getTargetSource(); 150 try { 151 if (this.advised.exposeProxy) { 152 // Make invocation available if necessary. 153 oldProxy = AopContext.setCurrentProxy(proxy); 154 setProxyContext = true; 155 } 156 // Get as late as possible to minimize the time we "own" the target, in case it comes from a pool... 157 target = targetSource.getTarget(); 158 Class<?> targetClass = (target != null ? target.getClass() : null); 159 List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);//根據將要執行的目標方法獲取攔截器鏈 160 Object retVal; 161 // Check whether we only have one InvokerInterceptor: that is, 162 // no real advice, but just reflective invocation of the target. 163 if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) { 164 // We can skip creating a MethodInvocation: just invoke the target directly. 165 // Note that the final invoker must be an InvokerInterceptor, so we know 166 // it does nothing but a reflective operation on the target, and no hot 167 // swapping or fancy proxying. 168 Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args); 169 retVal = methodProxy.invoke(target, argsToUse); 170 } 171 else { 172 // We need to create a method invocation... 173 retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();//執行攔截器鏈 174 } 175 retVal = processReturnType(proxy, target, method, retVal); 176 return retVal; 177 } 178 finally { 179 if (target != null && !targetSource.isStatic()) { 180 targetSource.releaseTarget(target); 181 } 182 if (setProxyContext) { 183 // Restore old proxy. 184 AopContext.setCurrentProxy(oldProxy); 185 } 186 } 187 } 188 }
下面我們可以通過調試代碼的方式來探究攔截器的調用。在這里攔截器是通過鏈式調用的方法按照順序依次執行,我們可以通過時序圖來很好的發現其調用邏輯。
好了,不知道通過源碼閱讀大家有沒有對Spring AOP有了一個全新的認識呢?有任何疑問歡迎留言喔~