今天再來(lái)聊一個(gè) Spring 中的冷門(mén)知識(shí):Bean 的處理不走正常流程,而是提前進(jìn)行 AOP。
在 Bean 創(chuàng)建的過(guò)程中,會(huì)先給 BeanPostProcessor 一個(gè)返回代理對(duì)象的機(jī)會(huì):
@Overrideprotected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException { //省略。。。 try { // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance. Object bean = resolveBeforeInstantiation(beanName, mbdToUse); if (bean != null) { return bean; } } catch (Throwable ex) { throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName, "BeanPostProcessor before instantiation of bean failed", ex); } try { Object beanInstance = doCreateBean(beanName, mbdToUse, args); if (logger.isTraceEnabled()) { logger.trace("Finished creating instance of bean '" + beanName + "'"); } return beanInstance; } //省略。。。}
小伙伴們看,這里的 resolveBeforeInstantiation 方法就是給 BeanPostProcessor 一個(gè)返回代理對(duì)象的機(jī)會(huì),在這個(gè)方法中,最終就會(huì)觸發(fā)到 InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation 方法,而在 postProcessBeforeInstantiation 方法中,會(huì)先判斷當(dāng)前 bean 是否是 AOP 相關(guān)類(lèi)等:
@Overridepublic Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) { Object cacheKey = getCacheKey(beanClass, beanName); if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) { if (this.advisedBeans.containsKey(cacheKey)) { return null; } if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) { this.advisedBeans.put(cacheKey, Boolean.FALSE); return null; } } TargetSource targetSource = getCustomTargetSource(beanClass, beanName); if (targetSource != null) { if (StringUtils.hasLength(beanName)) { this.targetSourcedBeans.add(beanName); } Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource); Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource); this.proxyTypes.put(cacheKey, proxy.getClass()); return proxy; } return null;}
這里主要來(lái)說(shuō)說(shuō) getCustomTargetSource 中的邏輯。
先來(lái)說(shuō)什么情況下會(huì)走到 getCustomTargetSource 方法:當(dāng)前 Bean 不是代理對(duì)象,也不是 AOP 相關(guān)的類(lèi),就是一個(gè)普普通通的常規(guī)類(lèi),那么就會(huì)走到 getCustomTargetSource 方法這里來(lái),這里失去查找到一個(gè) TargetSource 對(duì)象,然后根據(jù)該對(duì)象創(chuàng)建當(dāng)前 bean 的代理對(duì)象并返回,如果返回了代理對(duì)象,那么后續(xù)的 bean 創(chuàng)建流程就不執(zhí)行了。
我們來(lái)看下這個(gè)方法的源碼:
@Nullableprotected TargetSource getCustomTargetSource(Class<?> beanClass, String beanName) { // We can't create fancy target sources for directly registered singletons. if (this.customTargetSourceCreators != null && this.beanFactory != null && this.beanFactory.containsBean(beanName)) { for (TargetSourceCreator tsc : this.customTargetSourceCreators) { TargetSource ts = tsc.getTargetSource(beanClass, beanName); if (ts != null) { return ts; } } } // No custom TargetSource found. return null;}
可以看到,這里就是當(dāng)前類(lèi) AbstractAutoProxyCreator 中有一個(gè) customTargetSourceCreators 變量,現(xiàn)在就是遍歷該變量,通過(guò)這個(gè)集合中保存的 TargetSourceCreator 來(lái)創(chuàng)建 TargetSource 對(duì)象。
TargetSourceCreator 是一個(gè)接口,這個(gè)接口只有一個(gè)抽象類(lèi) AbstractBeanFactoryBasedTargetSourceCreator,我們來(lái)看下 AbstractBeanFactoryBasedTargetSourceCreator 中的 getTargetSource 方法是怎么執(zhí)行的:
@Override@Nullablepublic final TargetSource getTargetSource(Class<?> beanClass, String beanName) { AbstractBeanFactoryBasedTargetSource targetSource = createBeanFactoryBasedTargetSource(beanClass, beanName); if (targetSource == null) { return null; } DefaultListableBeanFactory internalBeanFactory = getInternalBeanFactoryForBean(beanName); // We need to override just this bean definition, as it may reference other beans // and we're happy to take the parent's definition for those. // Always use prototype scope if demanded. BeanDefinition bd = getConfigurableBeanFactory().getMergedBeanDefinition(beanName); GenericBeanDefinition bdCopy = new GenericBeanDefinition(bd); if (isPrototypeBased()) { bdCopy.setScope(BeanDefinition.SCOPE_PROTOTYPE); } internalBeanFactory.registerBeanDefinition(beanName, bdCopy); // Complete configuring the PrototypeTargetSource. targetSource.setTargetBeanName(beanName); targetSource.setBeanFactory(internalBeanFactory); return targetSource;}
首先,TargetSource 對(duì)象是通過(guò) createBeanFactoryBasedTargetSource 方法來(lái)創(chuàng)建的,這個(gè)方法是一個(gè)抽象方法,將來(lái)在子類(lèi)中被實(shí)現(xiàn)。
接下來(lái)會(huì)調(diào)用 getInternalBeanFactoryForBean 方法創(chuàng)建一個(gè)新的內(nèi)部容器 internalBeanFactory,本質(zhì)上這個(gè) internalBeanFactory 其實(shí)是一個(gè)子容器,現(xiàn)有的容器將作為這個(gè)子容器的父容器。
接下來(lái)就是獲取到當(dāng)前 beanName 所對(duì)應(yīng)的 BeanDefinition,然后進(jìn)行屬性配置,并注冊(cè)到內(nèi)部容器中,最后返回 targetSource 對(duì)象。
我們來(lái)看下這里的 getInternalBeanFactoryForBean 方法:
protected DefaultListableBeanFactory getInternalBeanFactoryForBean(String beanName) { synchronized (this.internalBeanFactories) { return this.internalBeanFactories.computeIfAbsent(beanName, name -> buildInternalBeanFactory(getConfigurableBeanFactory())); }}protected DefaultListableBeanFactory buildInternalBeanFactory(ConfigurableBeanFactory containingFactory) { // Set parent so that references (up container hierarchies) are correctly resolved. DefaultListableBeanFactory internalBeanFactory = new DefaultListableBeanFactory(containingFactory); // Required so that all BeanPostProcessors, Scopes, etc become available. internalBeanFactory.copyConfigurationFrom(containingFactory); // Filter out BeanPostProcessors that are part of the AOP infrastructure, // since those are only meant to apply to beans defined in the original factory. internalBeanFactory.getBeanPostProcessors().removeIf(beanPostProcessor -> beanPostProcessor instanceof AopInfrastructureBean); return internalBeanFactory;}
這個(gè)其實(shí)就是正常的容器創(chuàng)建,倒也沒(méi)啥好說(shuō)的,但是有幾個(gè)需要注意的點(diǎn):
好了,這就是大致的 AOP 提前生成原理,接下來(lái)松哥寫(xiě)一個(gè)案例我們一起來(lái)看下。
首先,我們先來(lái)自定義一個(gè) TargetSource:
public class UserServiceTargetSource extends AbstractBeanFactoryBasedTargetSource { @Override public Object getTarget() throws Exception { return getBeanFactory().getBean(getTargetBeanName()); } @Override public boolean isStatic() { return true; }}
關(guān)于 TargetSource 本身,松哥在之前的 Spring 源碼視頻中已經(jīng)和大家介紹過(guò)很多了,這里我就不再啰嗦了。
接下來(lái)自定義 TargetSourceCreator:
public class CustomTargetSourceCreator extends AbstractBeanFactoryBasedTargetSourceCreator { @Override protected AbstractBeanFactoryBasedTargetSource createBeanFactoryBasedTargetSource(Class<?> beanClass, String beanName) { if (getBeanFactory() instanceof ConfigurableListableBeanFactory) { if (beanClass.isAssignableFrom(UserService.class)) { return new UserServiceTargetSource(); } } return null; }}
如果要?jiǎng)?chuàng)建的 bean 是 UserService 的話(huà),那么就給返回一個(gè) UserServiceTargetSource 對(duì)象。
最后,也是最關(guān)鍵的一步,根據(jù)前面的分析,TargetSourceCreator 是存在于 AnnotationAwareAspectJAutoProxyCreator 這樣一個(gè) InstantiationAwareBeanPostProcessor 類(lèi)型的后置處理器中的,因此,我們要想辦法把自定義的 TargetSourceCreator 設(shè)置給 AnnotationAwareAspectJAutoProxyCreator,如下:
@Componentpublic class SetCustomTargetSourceCreator implements BeanPostProcessor, PriorityOrdered, BeanFactoryAware { private BeanFactory beanFactory; @Override public int getOrder() { return Integer.MIN_VALUE; } @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { if(bean instanceof AnnotationAwareAspectJAutoProxyCreator) { AnnotationAwareAspectJAutoProxyCreator annotationAwareAspectJAutoProxyCreator = (AnnotationAwareAspectJAutoProxyCreator)bean; CustomTargetSourceCreator customTargetSourceCreator = new CustomTargetSourceCreator(); customTargetSourceCreator.setBeanFactory(beanFactory); annotationAwareAspectJAutoProxyCreator.setCustomTargetSourceCreators(customTargetSourceCreator); } return bean; } @Override public void setBeanFactory(BeanFactory beanFactory) throws BeansException { this.beanFactory = beanFactory; }}
AnnotationAwareAspectJAutoProxyCreator 本身就是一個(gè) BeanPostProcessor,我們現(xiàn)在要做的就是修改這個(gè) BeanPostProcessor,BeanPostProcessor 是在 Spring 容器啟動(dòng)時(shí)候的 refresh 方法中去初始化的。
BeanPostProcessor 初始化的時(shí)候,先初始化實(shí)現(xiàn)了 PriorityOrdered 接口的,再初始化實(shí)現(xiàn)了 Ordered 接口的,最后再去初始化那些沒(méi)有實(shí)現(xiàn)任何排序接口的 BeanPostProcessor。
而我們這里 SetCustomTargetSourceCreator 一定要趕在 AnnotationAwareAspectJAutoProxyCreator 之前進(jìn)行初始化,這樣,當(dāng) AnnotationAwareAspectJAutoProxyCreator 進(jìn)行初始化的時(shí)候,就會(huì)用到 SetCustomTargetSourceCreator 這樣一個(gè)后置處理器,進(jìn)而在該處理器中修改 AnnotationAwareAspectJAutoProxyCreator 的屬性。
AnnotationAwareAspectJAutoProxyCreator 類(lèi)間接實(shí)現(xiàn)了 Ordered 接口,默認(rèn)優(yōu)先級(jí)是最低,但是在 Spring 容器啟動(dòng)時(shí),在處理 BeanFactoryPostProcessor 時(shí)(具體是 ConfigurationClassPostProcessor),將其優(yōu)先級(jí)設(shè)置為最高。
所以,我們?nèi)绻胍屪远x的 SetCustomTargetSourceCreator 搶在 AnnotationAwareAspectJAutoProxyCreator 之前執(zhí)行,那么就只能讓 SetCustomTargetSourceCreator 去實(shí)現(xiàn) PriorityOrdered 接口了,實(shí)現(xiàn) PriorityOrdered 接口之后,重寫(xiě) getOrder 方法,這個(gè)方法返回值是什么無(wú)所謂,反正都會(huì)在實(shí)現(xiàn)了 Ordered 接口的 BeanPostProcessor 之前執(zhí)行。
最后,我們?cè)僭趩?dòng)類(lèi)上開(kāi)啟自動(dòng)代理即可:
@Configuration@ComponentScan@EnableAspectJAutoProxypublic class JavaConfig {}
大功告成。
這樣,當(dāng) Spring 容器創(chuàng)建一個(gè) Bean 的時(shí)候,就會(huì)提前被 BeanPostProcessor 攔截,然后給出一個(gè) TargetSource,進(jìn)而據(jù)此創(chuàng)建代理對(duì)象,這樣就不需要后續(xù)常規(guī)的 Bean 創(chuàng)建流程了。好啦,感興趣的小伙伴可以自己去試一試哦~
本文鏈接:http://www.tebozhan.com/showinfo-26-15721-0.htmlSpring 冷知識(shí):一個(gè)提前 AOP 的機(jī)會(huì)
聲明:本網(wǎng)頁(yè)內(nèi)容旨在傳播知識(shí),若有侵權(quán)等問(wèn)題請(qǐng)及時(shí)與本網(wǎng)聯(lián)系,我們將在第一時(shí)間刪除處理。郵件:2376512515@qq.com