Spring 版本 4.3.2java
在拿到 Bean 實例之後,會經歷一系列的初始化工做,如:工廠回調、init 方法、後處理器在 Bean 初始化先後的處理等,在通常狀況下(非 factory-method 建立的 Bean 等),AOP代理對象的建立就在後處理器的處理方法中實現。spring
以 AbstractAutowireCapableBeanFactory 類中的 initializeBean 方法做爲起始點進行跟蹤緩存
/** * Initialize the given bean instance, applying factory callbacks * as well as init methods and bean post processors. * <p>Called from {@link #createBean} for traditionally defined beans, * and from {@link #initializeBean} for existing bean instances. * * 初始化給定的 bean 實例,應用工廠回調方法以及 init 方法和 bean 的後處理器。 * 該方法會被傳統定義 bean 的 createBean 方法所調用,也會被重載方法所引用 */ protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) { if (System.getSecurityManager() != null) { AccessController.doPrivileged((PrivilegedAction<Object>) () -> { invokeAwareMethods(beanName, bean); return null; }, getAccessControlContext()); } else { invokeAwareMethods(beanName, bean); } Object wrappedBean = bean; if (mbd == null || !mbd.isSynthetic()) { // 後處理器的前調用 wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName); } try { invokeInitMethods(beanName, wrappedBean, mbd); } catch (Throwable ex) { throw new BeanCreationException( (mbd != null ? mbd.getResourceDescription() : null), beanName, "Invocation of init method failed", ex); } if (mbd == null || !mbd.isSynthetic()) { // 初始化後,進行後處理器的後調用,跟蹤此方法 wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName); } return wrappedBean; }
依然在 AbstractAutowireCapableBeanFactory 類中。app
拿到 BeanFactory 中全部針對 Bean 的後處理器集合,依次調用。ide
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName) throws BeansException { Object result = existingBean; for (BeanPostProcessor processor : getBeanPostProcessors()) { // 利用處理器的處理方法,對 bean 實例進行處理,並返回一個對象 Object current = processor.postProcessAfterInitialization(result, beanName); if (current == null) { return result; } result = current; } return result; }
在後處理器集合中,有一個處理器叫作 AnnotationAwareAspectJAutoProxyCreator 建立器,該處理器在解析<aop:config>
標籤、或者解析相關注解時被註冊到工廠中,以下:post
// 若是必要的話註冊AspectJ自動代理建立器 public static BeanDefinition registerAspectJAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry, Object source) { // 傳遞了 AspectJAwareAdvisorAutoProxyCreator 的 Class,進入這個方法 return registerOrEscalateApcAsRequired(AspectJAwareAdvisorAutoProxyCreator.class, registry, source); } private static BeanDefinition registerOrEscalateApcAsRequired(Class<?> cls, BeanDefinitionRegistry registry, Object source) { Assert.notNull(registry, "BeanDefinitionRegistry must not be null"); //工廠中是否已經註冊了 org.springframework.aop.config.internalAutoProxyCreator if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) { BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME); //若是已經有註冊了 internalAutoProxyCreator,而且和入參傳遞的Class不是同一個Class, //那麼就根據優先級進行選擇 if (!cls.getName().equals(apcDefinition.getBeanClassName())) { //類 AopConfigUtils 中有個 ArrayList 屬性 APC_PRIORITY_LIST,在類靜態構造中依次加入了 //幾個建立器,這個方法就是查找某個建立器在 APC_PRIORITY_LIST 中的索引,若是沒有找到就報錯 int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName()); int requiredPriority = findPriorityForClass(cls); // internalAutoProxyCreator 的索引爲0,入參的 AspectJAwareAdvisorAutoProxyCreator // 索引爲1,後者要大,因此從新設置下 apcDefinition 的 beanClass if (currentPriority < requiredPriority) { apcDefinition.setBeanClassName(cls.getName()); } } //直接返回null return null; } // 若是沒有註冊 internalAutoProxyCreator ,組裝一個 Bean Definition,以 // AspectJAwareAdvisorAutoProxyCreator 做爲 bean Class,而後註冊到工廠中 RootBeanDefinition beanDefinition = new RootBeanDefinition(cls); beanDefinition.setSource(source); beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE); beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition); return beanDefinition; }
從上面能夠看見建立器 AnnotationAwareAspectJAutoProxyCreator 的註冊通過,Bean Definition 是對 Bean 的描述,建立 bean 對象時,會以 Bean Definition 爲依據進行實例化和初始化。優化
查看建立器的處理方法postProcessAfterInitialization
ui
該方法在建立器的超類 AbstractAutoProxyCreator 中實現this
/** * Create a proxy with the configured interceptors if the bean is * identified as one to proxy by the subclass. * * 若是 bean 被定義爲子類代理,則使用已配置的攔截器建立代理 */ @Override public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) { if (bean != null) { Object cacheKey = getCacheKey(bean.getClass(), beanName); if (!this.earlyProxyReferences.contains(cacheKey)) { // 緩存中沒有的狀況 return wrapIfNecessary(bean, beanName, cacheKey); } } return bean; } /** * Wrap the given bean if necessary, i.e. if it is eligible for being proxied. * * 必要的話包裝給定的 bean,即,他有資格被代理 */ protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) { if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) { return bean; } // advisedBeans 存放 bean 是否能夠被代理的信息,做爲緩存,避免重複判斷 // Map<Object, Boolean> advisedBeans = new ConcurrentHashMap<> if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) { return bean; } if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) { // 若是 bean 是一些特殊的類,好比 Pointcut/Advisor,又或者沒有 @Aspect 註解等 // 這些 bean 不該該被代理,信息存放到 advisedBeans 集合中 this.advisedBeans.put(cacheKey, Boolean.FALSE); return bean; } // Create proxy if we have advice. // 若是有通知,建立代理 // 拿到全部匹配該 bean 的通知,若是使用了切入點表達式或者 AspectJ 風格的加強, // 還須要在通知鏈的開始處添加 ExposeInvocationInterceptor 攔截器 Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null); if (specificInterceptors != DO_NOT_PROXY) { // 通知鏈不爲null,能夠代理 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; }
該方法在 AbstractAutoProxyCreator 中實現lua
/** * Create an AOP proxy for the given bean. * * 爲指定的 bean 建立一個 AOP 代理 */ protected Object createProxy(Class<?> beanClass, @Nullable String beanName, @Nullable Object[] specificInterceptors, TargetSource targetSource) { if (this.beanFactory instanceof ConfigurableListableBeanFactory) { // 在 beanFactory 中,beanName 有對應的 BeanDefinition,此方法就是爲 BeanDefinition 的 // attributes 屬性添加鍵值對,key 爲 xxx.originalTargetClass , value 包含了 targetSource AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass); } ProxyFactory proxyFactory = new ProxyFactory(); // 將建立器中的一些屬性拷貝到新建立的代理工廠 proxyFactory.copyFrom(this); // proxyTargetClass 屬性對代理方式的肯定有很是大的影響 // 當從建立器中拷貝的屬性 proxyFactory 爲 false 時,下面的兩個方法須要詳細跟蹤 if (!proxyFactory.isProxyTargetClass()) { if (shouldProxyTargetClass(beanClass, beanName)) { proxyFactory.setProxyTargetClass(true); } else { evaluateProxyInterfaces(beanClass, proxyFactory); } } // 對攔截器或者通知進行包裝,包裝成Advisor對象 Advisor[] advisors = buildAdvisors(beanName, specificInterceptors); // 在代理工廠中添加 Advisor 通知鏈 proxyFactory.addAdvisors(advisors); proxyFactory.setTargetSource(targetSource); // 子類中若是沒有覆蓋,那麼此方法爲空實現 customizeProxyFactory(proxyFactory); proxyFactory.setFrozen(this.freezeProxy); if (advisorsPreFiltered()) { proxyFactory.setPreFiltered(true); } // 經過代理工廠獲取代理 return proxyFactory.getProxy(getProxyClassLoader()); }
proxyTargetClass 布爾屬性值的肯定對代理方式有着很是大的影響。
當配置了<aop:aspectj-autoproxy>
,使用註解方式時;又或者是使用xml配置<aop:config>
時,兩個標籤都具備的proxy-target-class
屬性默認爲 false
那麼上述步驟建立 ProxyFactory 對象時,從建立器中拷貝的 proxyTargetClass 屬性則爲 false,進入條件
if (!proxyFactory.isProxyTargetClass()) { if (shouldProxyTargetClass(beanClass, beanName)) { proxyFactory.setProxyTargetClass(true); } else { evaluateProxyInterfaces(beanClass, proxyFactory); } }
先看第一個方法shouldProxyTargetClass
該方法在 AbstractAutoProxyCreator 中實現
/** * Determine whether the given bean should be proxied with its target class rather than its interfaces. * <p>Checks the {@link AutoProxyUtils#PRESERVE_TARGET_CLASS_ATTRIBUTE "preserveTargetClass" attribute} * of the corresponding bean definition. * * 肯定給定的bean是否應該使用其目標類而不是其接口進行代理。 * 檢查對應 bean definition 的 preserveTargetClass 屬性。 */ protected boolean shouldProxyTargetClass(Class<?> beanClass, String beanName) { return (this.beanFactory instanceof ConfigurableListableBeanFactory && AutoProxyUtils.shouldProxyTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName)); }
工廠默認實現 DefaultListableBeanFactory 類實現了 ConfigurableListableBeanFactory 接口。
跟蹤 AutoProxyUtils 類的 shouldProxyTargetClass 方法。
public static boolean shouldProxyTargetClass(ConfigurableListableBeanFactory beanFactory, String beanName) { // 工廠中有對應 beanName 的 bean definition 則進入條件 if (beanName != null && beanFactory.containsBeanDefinition(beanName)) { BeanDefinition bd = beanFactory.getBeanDefinition(beanName); // bean definition 的 attributes 屬性中是否有 // org.springframework.aop.framework.autoproxy.AutoProxyUtils.preserveTargetClass // 爲 key 的屬性,且 value 爲 ture return Boolean.TRUE.equals(bd.getAttribute(PRESERVE_TARGET_CLASS_ATTRIBUTE)); } return false; }
若是被代理 bean 對應的 bean definition 屬性中,存在org.springframework.aop.framework.autoproxy.AutoProxyUtils.preserveTargetClass
爲 key,且 值爲 true 的 attributes
那麼設置 proxyTargetClass 爲 ture
再看第二個方法
該方法在類 ProxyProcessorSupport 中實現,ProxyProcessorSupport 是 AbstractAutoProxyCreator 的父類
/** * Check the interfaces on the given bean class and apply them to the {@link ProxyFactory}, * if appropriate. * <p>Calls {@link #isConfigurationCallbackInterface} and {@link #isInternalLanguageInterface} * to filter for reasonable proxy interfaces, falling back to a target-class proxy otherwise. * * 檢查指定 bean class 上的接口,若是合適的話設置到 ProxyFactory 中。 * 調用 isConfigurationCallbackInterface 方法和 isInternalLanguageInterface 方法去過濾獲得 * 合理的代理接口,不然回退到 target-class proxy */ protected void evaluateProxyInterfaces(Class<?> beanClass, ProxyFactory proxyFactory) { // 此方法拿到類上及其父類上,全部的接口,不會遞歸獲取接口上的接口 Class<?>[] targetInterfaces = ClassUtils.getAllInterfacesForClass(beanClass, getProxyClassLoader()); boolean hasReasonableProxyInterface = false; // 遍歷全部的接口,並進行過濾 for (Class<?> ifc : targetInterfaces) { // 接口中不能有像 Aware、InitializingBean 等容器的回調接口 // 接口的 ClassName 也不能是以 .cglib.proxy.Factory 結尾或者是 groovy.lang.GroovyObject // 這樣的內部語言接口 if (!isConfigurationCallbackInterface(ifc) && !isInternalLanguageInterface(ifc) && ifc.getMethods().length > 0) { // 若是還有接口剩餘,則存在合適的代理接口 hasReasonableProxyInterface = true; break; } } if (hasReasonableProxyInterface) { // 將代理接口一個個添加到 proxyFactory 中 for (Class<?> ifc : targetInterfaces) { proxyFactory.addInterface(ifc); } } else { // 否者 proxyTargetClass 屬性設置爲 true proxyFactory.setProxyTargetClass(true); } }
總結一下兩個方法
當 xml 中沒有配置 proxyTargetClass 屬性,默認爲 false
若是被代理 bean 對應的 bean definition ,它的 attributes 屬性中,存在org.springframework.aop.framework.autoproxy.AutoProxyUtils.preserveTargetClass
爲 key,值爲 true 的鍵值對
那麼設置 proxyTargetClass 爲 ture
不然過濾全部接口,接口不能爲 Aware、InitializingBean 等容器的回調接口,也不能是內部語言接口
若是沒有合適的接口,proxyTargetClass 仍是設置爲 true 。
接下來看下代理工廠獲取代理的流程。
進入 ProxyFactory 類中,跟蹤 getProxy 方法
/** * Create a new proxy according to the settings in this factory. * <p>Can be called repeatedly. Effect will vary if we've added * or removed interfaces. Can add and remove interceptors. * <p>Uses the given class loader (if necessary for proxy creation). * * 根據這個 factory 的設置建立一個新的代理。 * 能夠被重複調用。若是咱們添加或者移除了接口,會有影響。 * 能夠添加和移除攔截器。 * 使用指定的類加載器(若是須要代理建立) */ public Object getProxy(@Nullable ClassLoader classLoader) { return createAopProxy().getProxy(classLoader); }
先跟蹤 createAopProxy 方法,此方法在 ProxyCreatorSupport 類中實現,ProxyFactory 是其子類。
/** * Subclasses should call this to get a new AOP proxy. They should <b>not</b> * create an AOP proxy with {@code this} as an argument. * * 子類應該調用這個方法去得到一個新的AOP代理。他們不該該用 this 做爲參數建立一個AOP代理 */ protected final synchronized AopProxy createAopProxy() { // 當AOP代理第一次被建立時,active會被設置爲true if (!this.active) { // 設置 active 爲 true,激活代理配置 activate(); } return getAopProxyFactory().createAopProxy(this); }
getAopProxyFactory 方法拿到的是 DefaultAopProxyFactory 的實例,它的接口是 AopProxyFactory
ProxyFactory 類間接繼承 AdvisedSupport ,AdvisedSupport 繼承 ProxyConfig ,做爲配置存在
ProxyFactory 類和 DefaultAopProxyFactory 並無繼承關係
以 ProxyFactory 類的實例爲參數,調用 createAopProxy 方法,繼續跟蹤
此方法在 DefaultAopProxyFactory 類中實現,採用 JDK proxy 代理仍是使用 cglib 代理,在這個方法中決定
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); } }
isOptimize
方法就是返回 ProxyFactory 的 optimize 屬性,爲布爾值
是否執行積極優化的含義。
優化一般意味着,在代理建立後,通知的變化不會帶來影響,默認下爲 false。
optimize 在此處也被做爲了一個判斷依據。
optimize 能夠參考文章:https://blog.csdn.net/zh199609/article/details/79710846
isProxyTargetClass
方法拿的則是 ProxyFactory 的 proxyTargetClass 屬性,前面已經跟蹤過。
hasNoUserSuppliedProxyInterfaces
方法在代理接口不存在,或者只有一個且是 SpringProxy 接口的子接口狀況下,才返回 true 。
當上述三個方法都返回 false 時,代理才走的 JDK proxy 代理,也就是接口代理。
當知足其中一個條件,進入方法後,還有一層篩選,要麼 target Class 是一個接口,要麼是 Proxy 類的子類,不然其他狀況都使用 cglib 代理,也就是類代理。
最後調用代理的 getProxy 方法。不一樣代理的實現,其實就是spring對 JDK 的 Proxy,或者 cglib 的 Enhancer 的封裝。最終完成AOP的實現。