摘要:

Spring的代理在上层中主要分为ProxyCreatorSupportProxyProcessorSupport,前者是基于代理工厂,后者是基于后置处理器,也可以认为后置就是自动代理器。当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的更多相关文章

  1. SpringBoot源码分析之SpringBoot的启动过程

    SpringBoot源码分析之SpringBoot的启动过程 发表于 2017-04-30   |   分类于 springboot  |   0 Comments  |   阅读次数 SpringB ...

  2. Springboot源码分析之项目结构

    Springboot源码分析之项目结构 摘要: 无论是从IDEA还是其他的SDS开发工具亦或是https://start.spring.io/ 进行解压,我们都会得到同样的一个pom.xml文件 4. ...

  3. 从SpringBoot源码分析 配置文件的加载原理和优先级

    本文从SpringBoot源码分析 配置文件的加载原理和配置文件的优先级     跟入源码之前,先提一个问题:   SpringBoot 既可以加载指定目录下的配置文件获取配置项,也可以通过启动参数( ...

  4. springboot源码分析-SpringApplication

    SpringApplication SpringApplication类提供了一种方便的方法来引导从main()方法启动的Spring应用程序 SpringBoot 包扫描注解源码分析 @Spring ...

  5. Springboot源码分析之jar探秘

    摘要: 利用IDEA等工具打包会出现springboot-0.0.1-SNAPSHOT.jar,springboot-0.0.1-SNAPSHOT.jar.original,前面说过它们之间的关系了, ...

  6. Springboot源码分析之代理三板斧

    摘要: 在Spring的版本变迁过程中,注解发生了很多的变化,然而代理的设计也发生了微妙的变化,从Spring1.x的ProxyFactoryBean的硬编码岛Spring2.x的Aspectj注解, ...

  7. Springboot源码分析之事务拦截和管理

    摘要: 在springboot的自动装配事务里面,InfrastructureAdvisorAutoProxyCreator ,TransactionInterceptor,PlatformTrans ...

  8. Springboot源码分析之Spring循环依赖揭秘

    摘要: 若你是一个有经验的程序员,那你在开发中必然碰到过这种现象:事务不生效.或许刚说到这,有的小伙伴就会大惊失色了.Spring不是解决了循环依赖问题吗,它是怎么又会发生循环依赖的呢?,接下来就让我 ...

  9. SpringBoot源码分析(二)启动原理

    Springboot的jar启动方式,是通过IOC容器启动 带动了Web容器的启动 而Springboot的war启动方式,是通过Web容器(如Tomcat)的启动 带动了IOC容器相关的启动 一.不 ...

随机推荐

  1. python安装及typora使用

    第一章 环境搭建 1.1Python安装 1.1.1python官网www.python.org 1.1.2根据电脑系统选择下载 1.1.3确定电脑系统属性,此处我们以win10的64位操作系统为例 ...

  2. ybc云计算思维

      YBC的云计算思维 计算机基础 一 计算机由5大单元组成 输入单元(鼠标 键盘) 存储单元(硬盘 内存) 逻辑单元(CPU) 控制单元(主板) 输出单元(显示器 音响 打印机) CPU CPU主要 ...

  3. markdown浅谈

    markdown是啥? markdown就是一种修饰网页/博客的方法,他能使网页变得更美观. 我们先解释一下代码框: 这个没法保留,就是把键盘左上角的⋅·⋅ 切换成英文变成`. 然后``` 在隔一行` ...

  4. baserecyclerviewadapterhelper -- setOnItemChildClickListener出现的问题

    出现问题 使用baserecyclerviewadapterhelper 的时候使用 adapter.setOnItemChildClickListener()方法,点击没有反应. adapter.s ...

  5. 【干货干货】configtxlator 工具介绍

    这一章我们对configtxlator做一个解说. 1, configtxlator 他是什么,有什么用? configtxlator 官方说明是用于生成Hyperledger结构通道配置的实用程序: ...

  6. ASP.NET Core MVC 之布局(Layout)

    1.什么是布局 布局通常包含常见的用户界面元素,例如应用头,导航或菜单元素和页脚,如图: 常见的HTML结构(例如脚本和样式表)也经常被应用程序中许多页面使用.所有这些共享元素都可以在布局中定义,然后 ...

  7. javascript获取指定区间范围随机数

    //获取指定区间范围随机数,包括lowerValue和upperValuefunction randomFrom(lowerValue,upperValue){    return Math.floo ...

  8. 基于dbunit进行mybatis DAO层Excel单元测试

    DAO层测试难点 可重复性,每次运行单元测试,得到的数据是重复的 独立性,测试数据与实际数据相互独立 数据库中脏数据预处理 不能给数据库中数据带来变化 DAO层测试方法 使用内存数据库,如H2.优点: ...

  9. 【linux日志】【日志分析】linux系统各日志文件的含义

    前段时间太忙,没有来得及管博客,最近时间充裕了,开始更新博客. 因为最近在看linux日志相关内容,把心得分享给大家 linux系统日志文件默认存放路径/var/log/ ls查看此路径下有哪些日志文 ...

  10. ubuntu .deb .tar.gz .tar.bz2 .rmp 和命令方式安装软件的方法

    今天在Ubuntu11.10中安装Google chrome浏览器是遇到了问题,下载好的".deb"格式的安装文件google-chrome-stable.deb双击后或者右键快捷 ...