目录

  • 1. 前言
  • 2. `Aop` 代理对象的产生
    • 2.1. `applyBeanPostProcessorsAfterInitialization()`
      • 2.1.1. `postProcessAfterInitialization()`
      • 2.1.2. `postProcessAfterInitialization()` 的具体实现
        • 2.1.2.1. `wrapIfNecessary()`
          • 2.1.2.1.1. `createProxy()` 创建代理对象
            • 2.1.2.1.1.1. `getProxy()`
            • 2.1.2.1.1.2. `createAopProxy()`
            • 2.1.2.1.1.3. `createAopProxy()`
            • 2.1.2.1.1.4. 使用 `JDK` 动态代理生成代理对象
  • `Aop` 代理对象产生流程步骤

1. 前言

我们接着 Spring Aop代理对象的产生(一) 来分析 Aop 代理对象的产生,上篇文章解读到了 AbstractAutowireCapableBeanFactoryinitializeBean(),我们继续

2. Aop 代理对象的产生

initializeBean() 方法重点关注 applyBeanPostProcessorsAfterInitialization 方法

Aop 的原理和实现就在其中,来到了AbstractAutowireCapableBeanFactoryapplyBeanPostProcessorsAfterInitialization 方法

2.1. applyBeanPostProcessorsAfterInitialization()

@Override
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)throws BeansException {// 初始化返回结果为existingBeanObject result = existingBean;// 遍历该工厂创建的所有实现了 BeanPostProcessors 接口的列表的 beanfor (BeanPostProcessor processor : getBeanPostProcessors()) {// 回调BeanPostProcessor#postProcessAfterInitialization来对现有的bean实例进行包装Object current = processor.postProcessAfterInitialization(result, beanName);// 一般processor对不感兴趣的bean会回调直接返回result,使其能继续回调后续的BeanPostProcessor// 但有些processor会返回null来中断其后续的BeanPostProcessorif (current == null) {// 直接返回result,中断其后续的BeanPostProcessor处理return result;}result = current;}return result;
}

2.1.1. postProcessAfterInitialization()

@Override
public Object postProcessAfterInitialization(Object bean, String beanName) {return bean;
}

查看 getBeanPostProcessors() 方法


查看 AnnotationAwareAspectJAutoProxyCreator 的类层次结构(查看),可知,其实现了 beanPostProcessor 接口,实现类为 AbstractAutoProxyCreator

2.1.2. postProcessAfterInitialization() 的具体实现

主要看这个方法,在 bean 初始化之后对生产出的 bean 进行包装代理

@Override
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {if (bean != null) {// 如果是普通bean,则返回beanName,如果是FactoryBean,则返回加上前缀&的&beanNameObject cacheKey = getCacheKey(bean.getClass(), beanName);// earlyProxyReferences中缓存的是已经创建好的代理对象if (!this.earlyProxyReferences.contains(cacheKey)) {return wrapIfNecessary(bean, beanName, cacheKey);}}return bean;
}

2.1.2.1. wrapIfNecessary()

判断 bean 是否需要被代理

protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {// 也是看看有没有缓存,有缓存对象就直接返回了if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {return bean;}// 如果该bean不需要被代理,则直接返回原始的bean对象if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {return bean;}if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {this.advisedBeans.put(cacheKey, Boolean.FALSE);return bean;}// 获取 bean 的 advices(通知或增强器)Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);if (specificInterceptors != DO_NOT_PROXY) {// 加入缓存中this.advisedBeans.put(cacheKey, Boolean.TRUE);// 通过createProxy方法创建代理对象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;
}

2.1.2.1.1. createProxy() 创建代理对象

AbstractAutoProxyCreatorcreateProxy() 创建代理对象

protected Object createProxy(Class<?> beanClass, @Nullable String beanName,@Nullable Object[] specificInterceptors, TargetSource targetSource) {if (this.beanFactory instanceof ConfigurableListableBeanFactory) {AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);}// 创建一个ProxyFactoryProxyFactory proxyFactory = new ProxyFactory();// 初始化ProxyFactoryproxyFactory.copyFrom(this);// 确定代理方式是使用JDK代理,还是使用Cglibif (!proxyFactory.isProxyTargetClass()) {if (shouldProxyTargetClass(beanClass, beanName)) {// proxyTargetClass默认是false使用JDK代理,反之使用CglibproxyFactory.setProxyTargetClass(true);}else {evaluateProxyInterfaces(beanClass, proxyFactory);}}// 就是把specificInterceptors中的advisors和commonInterceptors中的拦截器合并(如果有的话)在一起封装成Advisor返回Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);// 将advisors(本案例的四个通知)和源对象设置到proxyFactory上proxyFactory.addAdvisors(advisors);proxyFactory.setTargetSource(targetSource);customizeProxyFactory(proxyFactory);proxyFactory.setFrozen(this.freezeProxy);if (advisorsPreFiltered()) {proxyFactory.setPreFiltered(true);}// 真正去创建代理对象了return proxyFactory.getProxy(getProxyClassLoader());
}
2.1.2.1.1.1. getProxy()

在类 ProxyFactory

public Object getProxy(@Nullable ClassLoader classLoader) {return createAopProxy().getProxy(classLoader);
}
2.1.2.1.1.2. createAopProxy()

继续 ProxyCreatorSupport 类中的 createAopProxy() 方法

protected final synchronized AopProxy createAopProxy() {if (!this.active) {activate();}return getAopProxyFactory().createAopProxy(this);
}
2.1.2.1.1.3. createAopProxy()

获得被代理类的类型,以确定代理的方式

@Override
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {// 获得被代理类的类型,以确定代理的方式Class<?> targetClass = config.getTargetClass();// 如果对象类型是接口,或者是JAVA的动态代理类,那么就调用JDK的动态代理方法生成代理对象if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {return new JdkDynamicAopProxy(config);}// 否则使用CGLIB生成代理对象return new ObjenesisCglibAopProxy(config);}else {return new JdkDynamicAopProxy(config);}
}
2.1.2.1.1.4. 使用 JDK 动态代理生成代理对象

JdkDynamicAopProxy类实现了 InvocationHandler接口,则必定有 invoke 方法,来被调用,也就是用户调用 bean 相关方法时,此 invoke() 被真正调用

final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializablepublic Object getProxy(ClassLoader classLoader) {if (logger.isDebugEnabled()) {logger.debug("Creating JDK dynamic proxy: target source is " + this.advised.getTargetSource());}Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);// JDK 动态代理的标准用法return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}

Aop 代理对象产生流程步骤

  1. IOC 容器启动初始化时,首先会去一级缓存 singletonObjects 中去获取(肯定没有)
  2. 在根据当前 bean 的具体作用域,去初始化 bean
  3. 在做完 bean 的一些校验之后,会进行 bean 的实例化,即调用 createBeanInstance() 方法
  4. 如果存在 bean 的循环依赖的情况,会将当前已实例化的 bean put 进三级缓存 singletonFactories
  5. 接着会进行 bean 的相关属性填充,即调用 populateBean() 方法,注意此时还并没有产生代理对象
  6. 再接着会进行 bean 的初始化操作,即调用 initializeBean() 方法
  7. 遍历该工厂创建的所有实现了 BeanPostProcessors 接口的列表的 bean
  8. 判断这些 bean 需不需要被代理,如果不需要,则直接返回原始单例 bean,此时单例 bean 已完成向 IOC 容器的注册工作
  9. 如果需要,再确定代理方式是使用 JDK 代理,还是使用 Cglib
  10. 获取当前 bean 的所有 advices可理解为通知或增强器
  11. 根据代理方式,正式的去创建代理对象,此时代理对象就产生了

参考:https://blog.csdn.net/wuyuwei/article/details/88357698

Spring之Aop代理对象的产生(二)相关推荐

  1. 大数据WEB阶段Spring框架 AOP面向切面编程(二)

    Spring AOP面向切面编程(二) 一.切入点的execution表达式 execution的表达形式: execution(修饰符? 返回值类型 所在包类? 方法名(参数列表) 异常?) ?表示 ...

  2. Spring之AOP代理模式

    代理模式分类: 静态代理 动态代理 你要租房,不找房东,找中介,中介是房东的代理. 1.1静态代理 角色分析 抽象角色:一般会使用接口或者抽象类来解决 /*** @author LongXi* @cr ...

  3. 【java】通过spring通过AOP实现日志打印(二)

    本人菜鸡一个,上一篇文章说了说自己对AOP的理解,并留下了一个用spring注解实现AOP的坑,本文就来填填这个坑 该系列暂时有两篇文章: [java]java中的AOP思想(一):https://b ...

  4. Spring AOP 源码分析 - 创建代理对象

    1.简介 在上一篇文章中,我分析了 Spring 是如何为目标 bean 筛选合适的通知器的.现在通知器选好了,接下来就要通过代理的方式将通知器(Advisor)所持有的通知(Advice)织入到 b ...

  5. Spring AOP源码(2)—AspectJAwareAdvisorAutoProxyCreator创建代理对象【两万字】

      基于最新Spring 5.x,介绍了Spring AOP中的AspectJAwareAdvisorAutoProxyCreator自动代理创建者的工作流程,对于创建代理对象的源码进行了深度分析! ...

  6. spring事务--使用aop事务代理对象调用方法示例

    第一种获取aop代理对象的方式: 第二种方式获取aop代理对象:

  7. 动态代理以及对应Spring中AOP源码分析

    AOP(面向切面编程)在Spring中是被广泛应用的(例如日志,事务,权限等),而它的基本原理便是动态代理. 我们知道动态代理有两种:基于JDK的动态代理以及基于CGlib动态代理.以下是两种动态代理 ...

  8. Spring AOP源码解析(二)—— AOP引入

    目录 配置类 AopAutoConfiguration AspectJAutoProxyingConfiguration ClassProxyingConfiguration @EnableAspec ...

  9. spring的aop的动态代理机制都有哪些_Spring学习(4):Spring AOP

    Spring AOP说明 AOP(Aspect Oriented Pragraming)面向切面编程,AOP采用横向抽取机制,取代了传统纵向继承体系的重复性代码(性能监视.事务管理.安全检查.缓存). ...

  10. Spring通知类型及使用ProxyFactoryBean创建AOP代理

    Spring 通知类型 通知(Advice)其实就是对目标切入点进行增强的内容,Spring AOP 为通知(Advice)提供了 org.aopalliance.aop.Advice 接口. Spr ...

最新文章

  1. linux的变量用法
  2. 汇编语言-环境安装及各个寄存器介绍
  3. 虚数有物理意义吗?潘建伟范靖云团队最新量子力学研究同日登顶刊,引发基础数理热议...
  4. 【Linux C 多线程编程】互斥锁与条件变量
  5. POJ 1172 DFS
  6. 数据结构与算法 —— 链表linked list(01)
  7. android 和ios 混合式开发环境安装
  8. JavaScript中的.trim()无法在IE中运行
  9. shell中引号的应用
  10. 基于auto.js的网课自动签到软件以及facerig控制摄像头内容及auto.js新手教学
  11. NLP - AIML
  12. c语言蝴蝶图案代码,通达信指标公式,临界点蝴蝶图案出现,暴涨趋势出现(附源码)...
  13. CNVD-2022-10270/CNVD-2022-03672 向日葵RCE复现
  14. 基于vue的电商后台管理系统
  15. C语言基础and进阶——猜拳游戏(6个版本)
  16. 点击pv转化率_互联网中一些常用指标(PV、UV、蹦失率、转换率、退出率)
  17. 行测 加强题型 加强论证
  18. 中国天网系统有多牛叉?BBC 记者体验了一把
  19. 软件构造实验一问题解决方法及经验教训
  20. 汇编语言 贪吃蛇/鱼/变色/时间周期

热门文章

  1. 搜索算法(DFS,BFS等)
  2. python给每个key添加数据_一文看懂Python collections模块的高效数据类型
  3. TextView用法及实例
  4. Pgsql登录连接失败原因及解决方法
  5. 装tensorflow未果
  6. 计算机组成原理完整学习笔记(二):系统总线
  7. 小红帽系统进入oracle,11G RAC 安装在红帽6上,grid跑root.sh报错
  8. 西门子S7系列中间人攻击:防御和流量异常检测(三)
  9. 快速突破面试算法之排序篇
  10. android手机和荣耀哪个版本好,【求测评】荣耀v40轻奢版与荣耀X10哪款更好?图文爆料分析...