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

相关推荐
FAFU_kyp2 分钟前
Rust 语法速查
开发语言·后端·rust
Lubase3 分钟前
LuBase介绍&私有化部署教程
java·spring boot·低代码·gitee·vue
虫小宝14 分钟前
淘宝返利app多数据源设计:基于MyCat的分库分表与读写分离
java
sheji341615 分钟前
【开题答辩全过程】以 基于JSP的汽车租赁管理系统为例,包含答辩的问题和答案
java·开发语言·汽车
Victor35616 分钟前
Hibernate(24)Hibernate如何实现乐观锁?
后端
Victor35618 分钟前
Hibernate(23)什么是Hibernate的caching provider?
后端
wen__xvn21 分钟前
C++ 中 std::set 的用法
java·c++·c#
多米Domi01122 分钟前
0x3f 第21天 三更java进阶1-35 hot100普通数组
java·python·算法·leetcode·动态规划
步步为营DotNet32 分钟前
深深度探索.NET 中HttpClient的复用策略:提升性能与稳定性的关键度解析.NET 中IServiceCollection:构建可扩展服务体系的关键
java·网络·.net
牛马11143 分钟前
WidgetsFlutterBinding.ensureInitialized()在 Flutter Web 端启动流程的影响
java·前端·flutter