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

相关推荐
折哥的程序人生 · 物流技术专研7 小时前
第4篇:Lambda 简化策略模式(Java 8+)
java·设计模式·策略模式·函数式编程·lambda·代码简化·扩充系列
GoGeekBaird7 小时前
我开源了 BeeWeave,给 AI Agent 搭一个越用越懂你的知识创作台
后端·github
researcher-Jiang8 小时前
高性能计算之OpenMP——超算习堂学习1
android·java·学习
西门吹-禅9 小时前
java springboot N+1问题
java·开发语言·spring boot
DLYSB_9 小时前
生命通道:如何用 HIS 医疗系统直连网络声光终端,打造“零延误”的危急值响应网关?
java·网络·数据库·报警灯
weixin_BYSJ198710 小时前
SpringBoot + MySQL 乒乓球运动员信息管理系统项目实战--附源码04954
java·javascript·spring boot·python·django·flask·php
AI小码10 小时前
LLM 应用的缓存工程:当每次 API 调用都在燃烧成本
java·人工智能·spring·计算机·llm·编程·api
犀利豆10 小时前
AI in Harness(四)
人工智能·后端
Hui Baby10 小时前
Spring Security
java·后端·spring
IT笔记11 小时前
【Rust】Rust Match 模式匹配详解
java·开发语言·rust