扫二维码与项目经理沟通
我们在微信上24小时期待你的声音
解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流
摘要:
网站设计制作过程拒绝使用模板建站;使用PHP+MYSQL原生开发可交付网站源代码;符合网站优化排名的后台管理系统;网站建设、成都网站设计收费合理;免费进行网站备案等企业网站建设一条龙服务.我们是一家持续稳定运营了十载的创新互联网站建设公司。
Spring的代理在上层中主要分为ProxyCreatorSupport
和ProxyProcessorSupport
,前者是基于代理工厂,后者是基于后置处理器,也可以认为后置就是自动代理器。当spring容器中需要进行aop
进行织入的bean较多时,简单采用ProxyFacotryBean
无疑会增加很多工作量(因为每个Bean
!都得手动写一个)。所以自动代理就发挥它的作用了。
Spring中自动创建代理器分类
在内部,Spring使用BeanPostProcessor
让自动生成代理。基于BeanPostProcessor
的自动代理创建器的实现类,将根据一些规则在容器实例化Bean时为匹配的Bean
生成代理实例。代理创建器可以分为三类:
BeanNameAutoProxyCreator
DefaultAdvisorAutoProxyCreator
(它也支持前缀匹配)AnnotationAwareAspectJAutoProxyCreator
,它是我们的@EnableAspectJAutoProxy
导入的,这也是我们当下使用最为广泛的方式~BeanNameAutoProxyCreator
package com.github.dqqzj.springboot.aop; import org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator; import org.springframework.stereotype.Component; import javax.annotation.PostConstruct; /** * @author qinzhongjian * @date created in 2019-08-25 09:43 * @description: TODO * @since JDK 1.8.0_212-b10 */ @Component public class MyBeanNameAutoProxyCreator extends BeanNameAutoProxyCreator { @PostConstruct public void init() { super.setBeanNames("aopService", "abstractAutoProxyCreatorService"); super.setInterceptorNames("myMethodBeforeAdvice"); } }
如果你想用自己注册的@Bean
代替@EnableAspectJAutoProxy
默认给你注册的自动创建器AnnotationAwareAspectJAutoProxyCreator
,那么你可以注册一个Bean名称如下的Bean即可:
// 手动注册一个自动代理创建器,且名字务必叫AopConfigUtils.AUTO_PROXY_CREATOR_BEAN_NAME @Bean(AopConfigUtils.AUTO_PROXY_CREATOR_BEAN_NAME) public BeanNameAutoProxyCreator beanNameAutoProxyCreator() { ... }
AbstractAutoProxyCreator
public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware { ... }
AbstractAutoProxyCreator
是对自动代理创建器的一个抽象实现。最重要的是,它实现了SmartInstantiationAwareBeanPostProcessor
接口,因此会介入到Spring IoC容器Bean实例化的过程,在AbstractAutowireCapableBeanFactory
中有这样一段代码
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; } }
但是一般都不会生效的,因为这个resolveBeforeInstantiation
只是针对有自定义的targetsource
,因为自定义的targetsource不是spring的bean那么肯定不需要进行后续的一系列的实例化 初始化。所以可以在resolveBeforeInstantiation
直接进行proxy。简单的说吧 ,这个代码可以忽略不计,开发者一般用不到。
如何让resolveBeforeInstantiation直接返回bean?
package com.github.dqqzj.springboot.aop; import org.springframework.beans.BeansException; import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor; /** * @author qinzhongjian * @date created in 2019-08-25 11:35 * @description: TODO * @since JDK 1.8.0_212-b10 */ public class AopServiceInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor { @Override public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException { if (beanClass.isInstance(AopService.class)) { return new AopService(); } return null; } @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { return bean; } }
这个是spring第一次后置处理器的使用,如果这样直接就返回了,就相当于脱离了IOC的生命周期了一样,依赖注入,属性填充等这些都没有进行处理,所以使用的时候一定要注意,最好别使用这个功能。
在初始化bean的过程中后续还有2个特别重要的后置处理过程,对于循环依赖甚至异步注解事物注解等都有或多或少的影响,后续会继续分析它们。
小结:
SpringAOP
应尽量避免自己创建AutoProxyCreator
,内部机制及其复杂难免会由于没有想到的问题而出现其他不常见的问题,上面分享的内容很少,原因是我觉得熟悉这个架构设计师最关键的,各种子类的虽然实现大不相同,但是你想全部都记在脑海或者很熟悉那是不太现实的,只有熟悉他的设计才能遇见问题轻易的就能翻源码解决。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持创新互联。
我们在微信上24小时期待你的声音
解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流