Springboot源码分析之AbstractAdvisorAutoProxyCreator
摘要:
Spring的代理在上层中主要分为ProxyCreatorSupport和ProxyProcessorSupport,前者是基于代理工厂,后者是基于后置处理器,也可以认为后置就是自动代理器。当spring容器中需要进行aop进行织入的bean较多时,简单采用ProxyFacotryBean无疑会增加很多工作量(因为每个Bean!都得手动写一个)。所以自动代理就发挥它的作用了。

Spring中自动创建代理器分类
在内部,Spring使用BeanPostProcessor让自动生成代理。基于BeanPostProcessor的自动代理创建器的实现类,将根据一些规则在容器实例化Bean时为匹配的Bean生成代理实例。代理创建器可以分为三类:
- 基于Bean配置名规则的自动代理生成器:允许为一组特定配置名的Bean自动创建代理实例的代理创建器,实现类为
BeanNameAutoProxyCreator - 基于
Advisor匹配机制的自动代理创建器它会对容器中的所有Advisor进行扫描,自动将这些切面应用到匹配的Bean中,实现类是DefaultAdvisorAutoProxyCreator(它也支持前缀匹配) - 基于Bean中
AspectJ注解的自动代理生成器:为包含AspectJ注解的切入的Bean自动创建代理实例,实现类是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,内部机制及其复杂难免会由于没有想到的问题而出现其他不常见的问题,上面分享的内容很少,原因是我觉得熟悉这个架构设计师最关键的,各种子类的虽然实现大不相同,但是你想全部都记在脑海或者很熟悉那是不太现实的,只有熟悉他的设计才能遇见问题轻易的就能翻源码解决。
Springboot源码分析之AbstractAdvisorAutoProxyCreator的更多相关文章
- SpringBoot源码分析之SpringBoot的启动过程
SpringBoot源码分析之SpringBoot的启动过程 发表于 2017-04-30 | 分类于 springboot | 0 Comments | 阅读次数 SpringB ...
- Springboot源码分析之项目结构
Springboot源码分析之项目结构 摘要: 无论是从IDEA还是其他的SDS开发工具亦或是https://start.spring.io/ 进行解压,我们都会得到同样的一个pom.xml文件 4. ...
- 从SpringBoot源码分析 配置文件的加载原理和优先级
本文从SpringBoot源码分析 配置文件的加载原理和配置文件的优先级 跟入源码之前,先提一个问题: SpringBoot 既可以加载指定目录下的配置文件获取配置项,也可以通过启动参数( ...
- springboot源码分析-SpringApplication
SpringApplication SpringApplication类提供了一种方便的方法来引导从main()方法启动的Spring应用程序 SpringBoot 包扫描注解源码分析 @Spring ...
- Springboot源码分析之jar探秘
摘要: 利用IDEA等工具打包会出现springboot-0.0.1-SNAPSHOT.jar,springboot-0.0.1-SNAPSHOT.jar.original,前面说过它们之间的关系了, ...
- Springboot源码分析之代理三板斧
摘要: 在Spring的版本变迁过程中,注解发生了很多的变化,然而代理的设计也发生了微妙的变化,从Spring1.x的ProxyFactoryBean的硬编码岛Spring2.x的Aspectj注解, ...
- Springboot源码分析之事务拦截和管理
摘要: 在springboot的自动装配事务里面,InfrastructureAdvisorAutoProxyCreator ,TransactionInterceptor,PlatformTrans ...
- Springboot源码分析之Spring循环依赖揭秘
摘要: 若你是一个有经验的程序员,那你在开发中必然碰到过这种现象:事务不生效.或许刚说到这,有的小伙伴就会大惊失色了.Spring不是解决了循环依赖问题吗,它是怎么又会发生循环依赖的呢?,接下来就让我 ...
- SpringBoot源码分析(二)启动原理
Springboot的jar启动方式,是通过IOC容器启动 带动了Web容器的启动 而Springboot的war启动方式,是通过Web容器(如Tomcat)的启动 带动了IOC容器相关的启动 一.不 ...
随机推荐
- Web自动化测试 五 ----- selenium的等待和切换
一.selenium的三种等待 当执行python的selenium代码时,如果需要定位一个元素或者点击一个元素,需要考虑到网速等多方面原因,导致页面加载速度慢,元素还未加载出来,这样就会导致找不到对 ...
- 【干货干货】configtxlator 工具介绍
这一章我们对configtxlator做一个解说. 1, configtxlator 他是什么,有什么用? configtxlator 官方说明是用于生成Hyperledger结构通道配置的实用程序: ...
- python基础之元祖、嵌套,for循环、 enumerate、range的试用案例
元祖又叫做只读列表,可循环查询.可切片,元祖里的直接元素不能更改,但是若里面有嵌套的列表,则可以修改列表里的元素 tu = (1,2,3,'sun',[3,4,5,'cat']) tu[4][3] = ...
- Android App安装包瘦身计划
Android App安装包瘦身计划 Android App安装包体积优化: 理由, 指标和可以采用的方法. 本文内容归纳如下图: 为什么要安装包瘦身 安装包需要瘦身吗? 不需要吗? 安装包要瘦身的主 ...
- ~~面向对象进阶——__name__=="__main__"~~
进击のpython 面向对象进阶--__name__=="__main__" 前面我们在讲模块的时候,其实还有一个知识点没有很好的讲 那就是main和name 可能你们在看一些代码 ...
- 11. Java常用类
1. Scanner类 1.1 基本语法 java.util.Scanner 是 Java5 的新特征,我们可以通过 Scanner 类来获取用户的输入. Scanner s = new Scanne ...
- jQuery的核心思想
jQuery?----www.jQuery.com jQuery的理念:write less, do more jQuery的成就:世界排名前100的公司,46%都在使用jQuery,远远超过其他库, ...
- Eclipse "R cannot be resolved"问题
前两天 Eclipse 又遇到了这个问题.网上找了不少,不过最终还是没能解决我的问题,无奈重装了 Eclipse…… 搜索中找到了下面这几篇文章,常见的解决方法都在这里,还是不错的,分享一下: htt ...
- java 8中新的日期和时间API
java 8中新的日期和时间API 使用LocalDate和LocalTime LocalDate的实例是一个不可变对象,它只提供了简单的日期,并不含当天的时间信息.另外,它也不附带任何与时区相关的信 ...
- AUTOSAR学习之RTE - 基本概念
1.什么是RTE? The Run-Time Environment (RTE) is at the heart of the AUTOSAR ECU architecture. The RTE is ...