简单说说 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博客

相关推荐
爱学习的程序媛1 小时前
Python常用框架梳理
开发语言·后端·python·ai·web·后端框架·python框架
GISer_Jing1 小时前
Agent核心内容
后端·ai·langchain
budingxiaomoli2 小时前
Spring统一功能处理
java·后端·spring
某鹏3 小时前
网关选型:Go、Java、Graal 谁都不能完胜
后端
用户0247836530973 小时前
从屎山到防线:14 行状态迁移表,给任务系统装上防瞎跳闸门
后端
CQU_JIAKE4 小时前
11.13[体系结构】指标,五级流水线,八级流水线,虚实地址思考
后端
Flynn Liang4 小时前
可观测性与成本治理:一次对话的 17 个观测点
java·langchain·可观测性·micrometer·langchain4j·token 成本·llm 监控
金銀銅鐵4 小时前
带您看懂字节码指令(三):同一行加法,为什么有四种指令
java·jvm
panbook5 小时前
从0到1实现一个分布式时序数据库(三):主从复制、故障检测与切换
后端
上线再说5 小时前
图片从 8.2MB 压到 296KB:我把小程序图片链路的账单拆了一遍
后端