Spring AOP 实现原理分析

概述

Spring 动态代理两种实现:JDK 动态代理,CGLIB 动态代理

Spring默认使用JDK的动态代理实现AOP,类如果实现了接口,Spring就会使用这种方式实现动态代理;否则使用 CGLIB 实现

JDK 动态代理是通过实现 InvocationHandler 接口,重写 invoke,然后通过 Proxy.newProxyInstance 返回代理对象

CGLib直接操作字节码,生成类的子类,重写类的方法完成代理。注意,CGLIB 不能代理被 final 修饰的方法,因为 final 是不可变不可继承。

样例

JDK 动态代理

// 接口
public interface ITestA {
    void sayHello();
}

// 实现类
@Component
public class TestA implements ITestA {

    @Override
    public void sayHello() {
        System.out.println("Hello A");
    }
}

// 切面
@Aspect
@Component
public class AspectA {

    @Before(value = "execution(* com.example.springaop.service.TestA.*(..))")
    public void before(){
        System.out.println("Before hello");
    }
}

// 单元测试
@SpringBootTest
class SpringAopApplicationTests {

    @Autowired
    private ITestA iTestA;

    @Test
    void contextLoads() {
        iTestA.sayHello();
        System.out.println(iTestA.getClass().getSuperclass());
    }
}

若使用 Spring Boot 2.5.2 版本,application.properties 配置文件需开启一下配置spring.aop.proxy-target-class=false,否则会默认使用 CGLIB。

输出:

Before hello
Hello A
class java.lang.reflect.Proxy

CGLIB 动态代理

// 没有实现接口 
@Component
public class TestB {
    public void sayHello(){
        System.out.println("Hello B");
    }
}

@Aspect
@Component
public class AspectB {

    @Before(value = "execution(* com.example.springaop.cblib.TestB.*(..))")
    public void before(){
        System.out.println("befor B Hello");
    }
}

@SpringBootTest
class SpringAopApplicationTests {
    @Test
    void testB(){
        testB.sayHello();
        System.out.println(testB.getClass());
    }
}    

输出

befor B Hello
Hello B
class com.example.springaop.cblib.TestB$$EnhancerBySpringCGLIB$$3914f3c1

代理对象创建源码分析

从 Bean 的生命周期可以知道,Bean 在初始化阶段会执行 BeanPostProcessor 扩展点实现,直接从这里开始学习。

  1. BeanPostProcessor.postProcessAfterInitialization 执行 AOP 增强
public abstract class AbstractAutowireCapableBeanFactory {
    protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
        Object wrappedBean = bean;
        if (mbd == null || !mbd.isSynthetic()) {
            wrappedBean = this.applyBeanPostProcessorsBeforeInitialization(bean, beanName);
        }
        if (mbd == null || !mbd.isSynthetic()) {
        	// 执行后置拓展点
            wrappedBean = this.applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
        }
        return wrappedBean;
    }

	// 执行 BeanPostProcessor 拓展点后置方法
    public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName) throws BeansException {
        for(Iterator var4 = this.getBeanPostProcessors().iterator(); var4.hasNext(); result = current) {
            BeanPostProcessor processor = (BeanPostProcessor)var4.next();
            current = processor.postProcessAfterInitialization(result, beanName);
        }
        return result;
    }
}    
  1. AbstractAutoProxyCreator 重写 postProcessAfterInitialization 方法,通过 ProxyFactory.getProxy 方法得到代理对象。
public abstract class AbstractAutoProxyCreator {
	    public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
        if (bean != null) {
            Object cacheKey = this.getCacheKey(bean.getClass(), beanName);
            if (this.earlyProxyReferences.remove(cacheKey) != bean) {
            	// 返回代理
                return this.wrapIfNecessary(bean, beanName, cacheKey);
            }
        }
        return bean;
    }
    
    protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
		Object proxy = this.createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
    }
    
	protected Object createProxy(Class<?> beanClass, @Nullable String beanName, @Nullable Object[] specificInterceptors, TargetSource targetSource) {
		return proxyFactory.getProxy(classLoader);
	}
}
  1. ProxyFactory.getProxy 会先调用 ProxyCreatorSupport.getAopProxyFactory 创建工厂,然后再调用 createAopProxy 方法创建代理。
public class ProxyFactory extends ProxyCreatorSupport {
    public Object getProxy(@Nullable ClassLoader classLoader) {
        return this.createAopProxy().getProxy(classLoader);
    }
}

public class ProxyCreatorSupport extends AdvisedSupport { 
    protected final synchronized AopProxy createAopProxy() {
        if (!this.active) {
            this.activate();
        }
        return this.getAopProxyFactory().createAopProxy(this);
    }
}


public class DefaultAopProxyFactory implements AopProxyFactory, Serializable {

	public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
		// 
		if (NativeDetector.inNativeImage() || !config.isOptimize() && !config.isProxyTargetClass() && !this.hasNoUserSuppliedProxyInterfaces(config)) {
		    return new JdkDynamicAopProxy(config);
		} else {
		    Class<?> targetClass = config.getTargetClass();
		    if (targetClass == null) {
		        throw new AopConfigException("TargetSource cannot determine target class: Either an interface or a target is required for proxy creation.");
		    } else {
		    	// 如果不是接口 && 不是代理类,那么走 ObjenesisCglibAopProxy,否则走 JdkDynamicAopProxy
		        return (AopProxy)(!targetClass.isInterface() && !Proxy.isProxyClass(targetClass) ? new ObjenesisCglibAopProxy(config) : new JdkDynamicAopProxy(config));
		    }
		}
	}

    private boolean hasNoUserSuppliedProxyInterfaces(AdvisedSupport config) {
        Class<?>[] ifcs = config.getProxiedInterfaces();
        return ifcs.length == 0 || ifcs.length == 1 && SpringProxy.class.isAssignableFrom(ifcs[0]);
    }
}

参考

惊人!Spring5 AOP 默认使用Cglib ?从现象到源码深度分析

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值