简单说说 spring是如何实现AOP的(源码分析)

在spring生命周期流程中,有一个过程是执行BeanPostProcessor的后置方法

BeanPostProcessor 是一个接口,其实现有

aop实现的核心类是AbstractAutoProxyCreator,其位于spring-aop包下,实现了BeanPostProcessor

复制代码
//BeanPostProcessor的后置方法实现
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
    if (bean != null) {
        Object cacheKey = getCacheKey(bean.getClass(), beanName);
        if (this.earlyProxyReferences.remove(cacheKey) != bean) {
            //核心处理方法
            return wrapIfNecessary(bean, beanName, cacheKey);
        }
    }
    return bean;
}


protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
    ... 其他处理逻辑
    //返回当前bean的所有 advisor、advice、interceptor
    //如果定义了一个@Pointcut 会有一个advisor
    //如果定义了一个@Around 会有一个advisor
    Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
    //如果获取的结果是null,则这个bean没有被代理
    if (specificInterceptors != DO_NOT_PROXY) {
        //将当前的bean标记为代理类
        this.advisedBeans.put(cacheKey, Boolean.TRUE);
        //为bean创建代理对象
        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;
}

创建代理前的前置方法,这个方法核心做了三个事情

1 缺点该用cglib还是jdk动态代理,如果设置了使用cglib,则会使用cglib,如果没有设置,会根据是否有接口来进行判断,有接口使用jdk动态代理,没有接口使用cglib。

2 合并构建advisor,由于在上一步获取到的specificInterceptors,有多种情况,分别是advice、advisor和interceptor,这里要把这些都构建成advisor

3 创建代理:创建代理会根据是否使用cglib,然后创建不同的工厂对象进行创建不同的代理

复制代码
//specificInterceptors 携带的advisor信息
//targetSource 
protected Object createProxy(Class<?> beanClass, @Nullable String beanName,
			@Nullable Object[] specificInterceptors, TargetSource targetSource) {

		...
        //判断是否要转换使用cglib进行代理增强
		if (!proxyFactory.isProxyTargetClass()) {
            //根据是否有接口,将proxyTargetClass设置成true,就是使用cglib进行增强
			if (shouldProxyTargetClass(beanClass, beanName)) {
				proxyFactory.setProxyTargetClass(true);
			}
			else {
                //这里会判断是否有适合代理的接口,如果没有,还是会设置使用cglib
				evaluateProxyInterfaces(beanClass, proxyFactory);
			}
		}
        //将advice、interceptor和advisor都构造成advisor
		Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
		proxyFactory.addAdvisors(advisors);
		proxyFactory.setTargetSource(targetSource);
        //空方法,啥也不是
		customizeProxyFactory(proxyFactory);
        
		...
        //获取代理核心方法
		return proxyFactory.getProxy(getProxyClassLoader());
	}

传送门

简单说说 Bean的生命周期源码-CSDN博客

相关推荐
波波0071 小时前
ASP.NET Core 健康检查实战:不只是一个 /health 接口
后端·asp.net
小码哥_常1 小时前
Spring Boot 搭建邮件发送系统:开启你的邮件自动化之旅
后端
石榴树下的七彩鱼2 小时前
图片修复 API 接入实战:网站如何自动去除图片水印(Python / PHP / C# 示例)
图像处理·后端·python·c#·php·api·图片去水印
我叫黑大帅2 小时前
为什么TCP是三次握手?
后端·网络协议·面试
我叫黑大帅2 小时前
如何排查 MySQL 慢查询
后端·sql·面试
techdashen2 小时前
Rust项目公开征测:Cargo 构建目录新布局方案
开发语言·后端·rust
一 乐2 小时前
电影院|基于springboot + vue电影院购票管理系统(源码+数据库+文档)
java·数据库·vue.js·spring boot·论文·毕设·电影院购票管理管理系统
恼书:-(空寄2 小时前
JVM GC 日志分析 + 常见 GC 场景 + 实战参数调优
java·jvm
消失的旧时光-19432 小时前
Spring Boot 实战(五):接口工程化升级(统一返回 + 异常处理 + 错误码体系 + 异常流转机制)
java·spring boot·后端·解耦
Rust研习社2 小时前
Rust 智能指针 Cell 与 RefCell 的内部可变性
开发语言·后端·rust