• 【Spring 源码】AOP 的加载原理(二)


    【Spring 源码】AOP 的加载原理(二)



    一、选择创建策略

    主要代码:DefaultAopProxyFactory#createAopProxy()

    在之前讲到 DefaultAopProxyFactory 是默认的创建代理的工厂类,会根据传入的被代理类来选择不同的创建策略。

    @Override
    public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
       
    	if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
       
    		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.");
    		}
    		// 如果是接口或者是 Proxy 类型的 Bean 要创建 JDK 动态代理
    		if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
       
    			return new JdkDynamicAopProxy(config);
    		}
    
    		// 其他情况会创建 CGLib 动态代理
    		return new ObjenesisCglibAopProxy(config);
    	}
    	else {
       
    		// 使用 JDK 动态代理
    		return new JdkDynamicAopProxy(config);
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    1. JDK 动态代理

    JDK 动态代理

    【1】获取被代理的接口

    主要代码:JdkDynamicAopProxy#getProxy()

    在这个过程中,主要是通过 AopProxyUtils.completeProxiedInterfaces() 进行被代理接口的筛选,在 Java 中,我们都知道一个类只能继承一个父类,但是可以实现多个接口,所以要找到被代理的接口需要做一堆工作。

    @Override
    public Object getProxy(@Nullable ClassLoader classLoader) {
       
    	if (logger.isTraceEnabled()) {
       
    		logger.trace("Creating JDK dynamic proxy: " + this.advised.getTargetSource());
    	}
    	
    	// 获取需要代理的接口
    	Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
    	
    	// 找 EqualsAndHashCode 方法
    	findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
    	
    	// JDK 动态代理的获取目标类的主要方法
    	return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    【2】JDK 动态代理主要处理方法

    主要代码:JdkDynamicAopProxy#invoke()

    在方法中,会发现 this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass); 这么一行方法,这边主要是使用了责任链模式对 Advisors 进行封装成链,以便后续继续使用。

    @Override
    @Nullable
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
       
    	Object oldProxy = null;
    	boolean setProxyContext = false;
    
    	TargetSource targetSource = this.advised.targetSource;
    	Object target = null;
    
    	try {
       
    		// 目标未实现 equals 方法
    		if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
       
    			return equals(args[0]);
    		}
    		// 目标未实现 hashCode 方法
    		else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
       
    			return hashCode();
    		}
    		else if (method.getDeclaringClass() == DecoratingProxy.class) {
       
    			return AopProxyUtils.ultimateTargetClass(this.advised);
    		}
    		// 直接反射调用
    		else if (!this.advised.opaque && method.getDeclaringClass
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
  • 相关阅读:
    多线程的几种创建方式以及手写@Async异步注解
    30个Python常用极简代码,拿走就用
    并发编程(三)原子性(1)
    Nginx 转发时的一个坑,运维居然让我背锅
    浮动与定位的使用(结合案例版)
    umi浅用
    全球名校AI课程库(43)| 李宏毅 · 机器学习(&深度学习)课程『Machine Learning』
    B+树索引的管理
    系列六、Mybatis的一级缓存
    浅学Vue
  • 原文地址:https://blog.csdn.net/weixin_41645142/article/details/126879484