前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【小家Spring】Sping AOP中使用到的那些工具类盘点:AopUtils、AopConfigUtils、AspectJAopUtils 、AopProxyUtils、AopContext

【小家Spring】Sping AOP中使用到的那些工具类盘点:AopUtils、AopConfigUtils、AspectJAopUtils 、AopProxyUtils、AopContext

作者头像
YourBatman
发布2019-09-03 15:23:44
2.2K0
发布2019-09-03 15:23:44
举报
文章被收录于专栏:BAT的乌托邦BAT的乌托邦
前言

Spring AOP框架的代码结构组织得不可为不好,良好的面向对象的编程思想,其中很有一部分得益于它对代码的结构的把控。良好的封装、分层、隔离。而在其中起到重要作用的,便是本文要盘点的一些工具类。

Spring框架的工具类,其实它是分为内部工具类外部工具类的。如果是外部工具类,那是可以给调用者使用的,如果是内部工具类,那它一般都是在Spring的流程内部使用。

Spring AOP工具类盘点

对此我们先构造这么一个环境:

代码语言:javascript
复制
public interface HelloService {
    Object hello();
}
public class HelloServiceImpl implements HelloService {
    @Override
    public Object hello() {
        System.out.println("this is my method~~");
        return "service hello";
    }
	// 准备一个私有方法,测试用
    private void privateMethod() {
        System.out.println("privateMethod");
    }
}
代码语言:javascript
复制
    private static HelloService getProxy(Object targetObj){
        ProxyFactory proxyFactory = new ProxyFactory();
        proxyFactory.setTarget(targetObj);
        proxyFactory.addAdvice((MethodBeforeAdvice) (method, args1, target) -> {
            System.out.println("方法之前执行了~~~");
        });

        HelloService helloService = (HelloService) proxyFactory.getProxy();
        helloService.hello();
        System.out.println(helloService.getClass().getName()); //com.fsx.service.HelloServiceImpl$$EnhancerBySpringCGLIB$$9b28670f
        return helloService;
    }
AopUtils

该工具类是Spring非常重要的一个工具类。显然它是一个外部工具类,我们平时若想要对AOP做一些判断、处理,也是可议使用此工具类的。

下面我们参照一些Demo,来做演示:

代码语言:javascript
复制
    public static void main(String[] args) {
        HelloService helloService = getProxy(new HelloServiceImpl());
        //===============演示AopUtils==================

        // AopUtils.isAopProxy:是否是代理对象
        System.out.println(AopUtils.isAopProxy(helloService)); // true
        System.out.println(AopUtils.isJdkDynamicProxy(helloService)); // false
        System.out.println(AopUtils.isCglibProxy(helloService)); // true

        // 拿到目标对象
        System.out.println(AopUtils.getTargetClass(helloService)); //class com.fsx.service.HelloServiceImpl

        // selectInvocableMethod:方法@since 4.3  底层依赖于方法MethodIntrospector.selectInvocableMethod
        // 只是在他技术上做了一个判断: 必须是被代理的方法才行(targetType是SpringProxy的子类,且是private这种方法,且不是static的就不行)
        // Spring MVC的detectHandlerMethods对此方法有大量调用~~~~~
        Method method = ClassUtils.getMethod(HelloServiceImpl.class, "hello");
        System.out.println(AopUtils.selectInvocableMethod(method, HelloServiceImpl.class)); //public java.lang.Object com.fsx.service.HelloServiceImpl.hello()

        // 是否是equals方法
        // isToStringMethod、isHashCodeMethod、isFinalizeMethod  都是类似的
        System.out.println(AopUtils.isEqualsMethod(method)); //false

        // 它是对ClassUtils.getMostSpecificMethod,增加了对代理对象的特殊处理。。。
        System.out.println(AopUtils.getMostSpecificMethod(method,HelloService.class));
	}

接下来的几个方法都是关于Pointcut、Advisor的,看源码分析会更好:

代码语言:javascript
复制
public abstract class AopUtils {
	...
	// 判断一个切入点能否匹配一个指定的类型   显然默认是不支持引介匹配
	public static boolean canApply(Pointcut pc, Class<?> targetClass) {
		return canApply(pc, targetClass, false);
	}

	//判断一个切入点能否匹配一个指定的类型,是否支持引介匹配;
	public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) {
		Assert.notNull(pc, "Pointcut must not be null");
		if (!pc.getClassFilter().matches(targetClass)) {
			return false;
		}

		MethodMatcher methodMatcher = pc.getMethodMatcher();
		// 如果是恒等式true,那就毫无疑问全匹配楼
		if (methodMatcher == MethodMatcher.TRUE) {
			return true;
		}
		//IntroductionAwareMethodMatcher 是MethodMatcher的子类  增加了匹配方法:
		// boolean matches(Method method, @Nullable Class<?> targetClass, boolean hasIntroductions);
		IntroductionAwareMethodMatcher introductionAwareMethodMatcher = null;
		if (methodMatcher instanceof IntroductionAwareMethodMatcher) {
			introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher) methodMatcher;
		}

		Set<Class<?>> classes = new LinkedHashSet<>();
		if (!Proxy.isProxyClass(targetClass)) {
			classes.add(ClassUtils.getUserClass(targetClass));
		}
		classes.addAll(ClassUtils.getAllInterfacesForClassAsSet(targetClass));

		for (Class<?> clazz : classes) {
			Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz);
			for (Method method : methods) {
				if (introductionAwareMethodMatcher != null ?
						introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions) :
						methodMatcher.matches(method, targetClass)) {
					return true;
				}
			}
		}

		return false;
	}

	//判断一个建议(advisor)能否匹配一个指定的类型
	public static boolean canApply(Advisor advisor, Class<?> targetClass) {
		return canApply(advisor, targetClass, false);
	}
	// 同上,是否包含引介匹配
	// 这个原理很简单,判断是否是IntroductionAdvisor还是PointcutAdvisor,然后做对应判断即可
	public static boolean canApply(Advisor advisor, Class<?> targetClass, boolean hasIntroductions) {
		if (advisor instanceof IntroductionAdvisor) {
			return ((IntroductionAdvisor) advisor).getClassFilter().matches(targetClass);
		}
		else if (advisor instanceof PointcutAdvisor) {
			PointcutAdvisor pca = (PointcutAdvisor) advisor;
			return canApply(pca.getPointcut(), targetClass, hasIntroductions);
		}
		else {
			// It doesn't have a pointcut so we assume it applies.
			// 默认情况都是匹配的
			return true;
		}
	}

	//在给定的一组建议(advisor)中,返回能够匹配指定类型的建议者列表
	// 这个方法很总要:在自动代理创建器AbstractAdvisorAutoProxyCreator中,都是这样筛选的能够匹配上此类型的Advisor们~~~
	public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) {
		if (candidateAdvisors.isEmpty()) {
			return candidateAdvisors;
		}
		List<Advisor> eligibleAdvisors = new LinkedList<>();
	
		// 这里遍历了candidateAdvisors两次   注意这个技巧
		// 第一次遍历:找出所有的IntroductionAdvisor 类型的,并且canApply的Advisor们
		for (Advisor candidate : candidateAdvisors) {
			if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) {
				eligibleAdvisors.add(candidate);
			}
		}
		
		// hasIntroductions:如果上面不为空,这里就是true  然后继续便利  吧canApply的找出来
		boolean hasIntroductions = !eligibleAdvisors.isEmpty();
		for (Advisor candidate : candidateAdvisors) {
			if (candidate instanceof IntroductionAdvisor) {
				// already processed
				continue;
			}
			if (canApply(candidate, clazz, hasIntroductions)) {
				eligibleAdvisors.add(candidate);
			}
		}
		return eligibleAdvisors;
	}

	//通过反射,执行一个目标方法;这个方法其实就是method.invoke方法的更完善的方法,指在target对象上,使用args参数列表执行method
	@Nullable
	public static Object invokeJoinpointUsingReflection(@Nullable Object target, Method method, Object[] args)
			throws Throwable {
		try {
			ReflectionUtils.makeAccessible(method);
			return method.invoke(target, args);
		} catch (InvocationTargetException ex) { 
			throw ex.getTargetException();
		} catch (IllegalArgumentException ex) {
			throw new AopInvocationException("AOP configuration seems to be invalid: tried calling method [" + method + "] on target [" + target + "]", ex);
		} catch (IllegalAccessException ex) {
			throw new AopInvocationException("Could not access method [" + method + "]", ex);
		}
	}
}
AopConfigUtils

从名字可以看出,这个是关于AOP配置的工具类。因为配置AOP的方式有多种(比如xml、注解等),此工具类就是针对不同配置,提供不同的工具方法的。

它的好处是不管什么配置,最终走底层逻辑都让归一了~~~~

代码语言:javascript
复制
public abstract class AopConfigUtils {

	// 这是注册自动代理创建器,默认的BeanName(若想覆盖,需要使用这个BeanName)
	public static final String AUTO_PROXY_CREATOR_BEAN_NAME = "org.springframework.aop.config.internalAutoProxyCreator";

	// 按照升级顺序 存储自动代理创建器(注意这里是升级的顺序 一个比一个强的)
	private static final List<Class<?>> APC_PRIORITY_LIST = new ArrayList<>();
	static {
		APC_PRIORITY_LIST.add(InfrastructureAdvisorAutoProxyCreator.class);
		APC_PRIORITY_LIST.add(AspectJAwareAdvisorAutoProxyCreator.class);
		APC_PRIORITY_LIST.add(AnnotationAwareAspectJAutoProxyCreator.class);
	}

	// 这两个:注册的是`InfrastructureAdvisorAutoProxyCreator`  
	// 调用处为:AutoProxyRegistrar#registerBeanDefinitions(它是一个ImportBeanDefinitionRegistrar实现类) 
	// 而AutoProxyRegistrar使用处为CachingConfigurationSelector,和`@EnableCaching`注解有关
	// 其次就是AopNamespaceUtils有点用,这个下面再分析
	@Nullable
	public static BeanDefinition registerAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry,
			@Nullable Object source) {
		return registerOrEscalateApcAsRequired(InfrastructureAdvisorAutoProxyCreator.class, registry, source);
	}
	@Nullable
	public static BeanDefinition registerAspectJAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry) {
		return registerAspectJAutoProxyCreatorIfNecessary(registry, null);
	}
	
	// 下面这两个是注入:AspectJAwareAdvisorAutoProxyCreator
	// 目前没有地方默认调用~~~~和Aop的xml配置方案有关的
	@Nullable
	public static BeanDefinition registerAspectJAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry) {
		return registerAspectJAutoProxyCreatorIfNecessary(registry, null);
	}
	@Nullable
	public static BeanDefinition registerAspectJAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry,
			@Nullable Object source) {
		return registerOrEscalateApcAsRequired(AspectJAwareAdvisorAutoProxyCreator.class, registry, source);
	}

	// 这个就是最常用的,注入的是:AnnotationAwareAspectJAutoProxyCreator  注解驱动的自动代理创建器
	// `@EnableAspectJAutoProxy`注入进来的就是它了
	@Nullable
	public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry) {
		return registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry, null);
	}
	@Nullable
	public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry,
			@Nullable Object source) {
		return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
	}


	// 这两个方法,很显然,就是处理注解的两个属性值
	// proxyTargetClass:true表示强制使用CGLIB的动态代理
	// exposeProxy:true暴露当前代理对象到线程上绑定
	// 最终都会放到自动代理创建器得BeanDefinition 里面去~~~创建代理的时候会用到此属性值
	public static void forceAutoProxyCreatorToUseClassProxying(BeanDefinitionRegistry registry) {
		if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
			BeanDefinition definition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
			definition.getPropertyValues().add("proxyTargetClass", Boolean.TRUE);
		}
	}
	public static void forceAutoProxyCreatorToExposeProxy(BeanDefinitionRegistry registry) {
		if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
			BeanDefinition definition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
			definition.getPropertyValues().add("exposeProxy", Boolean.TRUE);
		}
	}

	//========上面的注册自动代理创建器IfNecessary之类的方法,最终都是调用了这里========
	@Nullable
	private static BeanDefinition registerOrEscalateApcAsRequired(Class<?> cls, BeanDefinitionRegistry registry,
			@Nullable Object source) {
		
		// 这里相当于,如果你自己定义了一个名称为这个的自动代理创建器,那也是ok的(需要注意的是使用工厂方法@Bean的方式定义,这里是会报错的)
		if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
			BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
			
			// 若使用@Bean的方法定义,这里apcDefinition.getBeanClassName()就是null,导致后面的findPriorityForClass(apcDefinition.getBeanClassName())就会报错~~~~~~~  需要特别的注意哦~~~~~
			if (!cls.getName().equals(apcDefinition.getBeanClassName())) {
				int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName());
				int requiredPriority = findPriorityForClass(cls);
				if (currentPriority < requiredPriority) {
					apcDefinition.setBeanClassName(cls.getName());
				}
			}
			return null;
		}

		// 绝大部分情况下都会走这里,new一个Bean定义信息出来,然后order属性值为HIGHEST_PRECEDENCE
		// role是:ROLE_INFRASTRUCTURE属于Spring框架自己使用的Bean
		// BeanName为:AUTO_PROXY_CREATOR_BEAN_NAME
		RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
		beanDefinition.setSource(source);
		beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);
		beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
		registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);
		return beanDefinition;
	}

	...findPriorityForClass的逻辑省略
}

备注:请尽量不要自定义自动代理创建器,也不要轻易使用低级别的创建器,若你对原理不是非常懂的话,慎重

AopNamespaceUtils

这个从名字可以看出,是处理Spring AOP命名空间的工具类。比如

代码语言:javascript
复制
xmlns:aop="http://www.springframework.org/schema/aop

处理这种xml里面的

代码语言:javascript
复制
<aop:config />
<aop:advice />

等这种。当然还有对proxy-target-classexpose-proxy的处理。因为接下来的重点都不在xml里,因此此处略过(最终它调用都是AopConfigUtils#XXXIfNecessary的方法,去注册不同的自动代理创建器的)

AopProxyUtils

我理解成它是对org.springframework.aop.support.AopUtils的一个补充。

代码语言:javascript
复制
    public static void main(String[] args) {
        HelloService helloService = getProxy(new HelloServiceImpl());
        //===============演示AopUtils==================

        // 注意:此处的入参必须是一个Advised:也就是被代理过的对象,否则返回null
        // 里面的TargetSource必须是SingletonTargetSource才会有所返回
        //@since 4.3.8
        System.out.println(AopProxyUtils.getSingletonTarget(helloService)); //com.fsx.service.HelloServiceImpl@17d677df
        // 获取一个代理对象的最终对象类型
        System.out.println(AopProxyUtils.ultimateTargetClass(helloService)); //class com.fsx.service.HelloServiceImpl
    }

接下俩的方法,才是这个工具类真正厉害的方法:

代码语言:javascript
复制
public abstract class AopProxyUtils {
	...
	//很牛逼的方法来了,判断一个advised真正需要代理的目标接口列表 
	// 这个方法在getProxy()上都有应用,非常的重要。核心实现事下面的这个私有方法
	public static Class<?>[] completeProxiedInterfaces(AdvisedSupport advised) {
		return completeProxiedInterfaces(advised, false);
	}
	// 很显然发现,最终代理出来的对象,除了实现了自己的接口外,还实现了额外的接口,如:
	// SpringProxy、Advised、DecoratingProxy等三个接口(备注:CGLIB代理未实现DecoratingProxy接口)
	static Class<?>[] completeProxiedInterfaces(AdvisedSupport advised, boolean decoratingProxy) {
		Class<?>[] specifiedInterfaces = advised.getProxiedInterfaces();
		if (specifiedInterfaces.length == 0) {
			// No user-specified interfaces: check whether target class is an interface.
			Class<?> targetClass = advised.getTargetClass();
			if (targetClass != null) {
				if (targetClass.isInterface()) {
					advised.setInterfaces(targetClass);
				}
				else if (Proxy.isProxyClass(targetClass)) {
					advised.setInterfaces(targetClass.getInterfaces());
				}
				specifiedInterfaces = advised.getProxiedInterfaces();
			}
		}
		boolean addSpringProxy = !advised.isInterfaceProxied(SpringProxy.class);
		boolean addAdvised = !advised.isOpaque() && !advised.isInterfaceProxied(Advised.class);
		boolean addDecoratingProxy = (decoratingProxy && !advised.isInterfaceProxied(DecoratingProxy.class));
		int nonUserIfcCount = 0;
		if (addSpringProxy) {
			nonUserIfcCount++;
		}
		if (addAdvised) {
			nonUserIfcCount++;
		}
		if (addDecoratingProxy) {
			nonUserIfcCount++;
		}
		Class<?>[] proxiedInterfaces = new Class<?>[specifiedInterfaces.length + nonUserIfcCount];
		System.arraycopy(specifiedInterfaces, 0, proxiedInterfaces, 0, specifiedInterfaces.length);
		int index = specifiedInterfaces.length;
		if (addSpringProxy) {
			proxiedInterfaces[index] = SpringProxy.class;
			index++;
		}
		if (addAdvised) {
			proxiedInterfaces[index] = Advised.class;
			index++;
		}
		if (addDecoratingProxy) {
			proxiedInterfaces[index] = DecoratingProxy.class;
		}
		return proxiedInterfaces;
	}

	//该方法用于获取一个代理对象中的用户定义的接口,即非(Advised接口体系)之外的其他接口
	public static Class<?>[] proxiedUserInterfaces(Object proxy) {
		Class<?>[] proxyInterfaces = proxy.getClass().getInterfaces();
		int nonUserIfcCount = 0;
		if (proxy instanceof SpringProxy) {
			nonUserIfcCount++;
		}
		if (proxy instanceof Advised) {
			nonUserIfcCount++;
		}
		if (proxy instanceof DecoratingProxy) {
			nonUserIfcCount++;
		}
		Class<?>[] userInterfaces = new Class<?>[proxyInterfaces.length - nonUserIfcCount];
		System.arraycopy(proxyInterfaces, 0, userInterfaces, 0, userInterfaces.length);
		Assert.notEmpty(userInterfaces, "JDK proxy must implement one or more interfaces");
		return userInterfaces;
	}

	//判断两个(即将)代理出来的对象是否相同
	public static boolean equalsInProxy(AdvisedSupport a, AdvisedSupport b) {
		return (a == b ||
				(equalsProxiedInterfaces(a, b) && equalsAdvisors(a, b) && a.getTargetSource().equals(b.getTargetSource())));
	}
	// 判断它哥俩的接口是否相同
	public static boolean equalsProxiedInterfaces(AdvisedSupport a, AdvisedSupport b) {
		return Arrays.equals(a.getProxiedInterfaces(), b.getProxiedInterfaces());
	}
	// 判断它哥俩的增强器(Advisor)是否相同
	public static boolean equalsAdvisors(AdvisedSupport a, AdvisedSupport b) {
		return Arrays.equals(a.getAdvisors(), b.getAdvisors());
	}
}

JDK代理和CGLIB代理的获取代理对象方法都用使用此方法:

代码语言:javascript
复制
	// JDK代理的获取代理对象~~~
	@Override
	public Object getProxy(@Nullable ClassLoader classLoader) {
		if (logger.isDebugEnabled()) {
			logger.debug("Creating JDK dynamic proxy: target source is " + this.advised.getTargetSource());
		}
		// 这里就是获取到所有需要被代理的接口
		Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
		findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
		return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
	}

AopProxyUtils中的方法不多,但是其中的ultimateTargetClass和completeProxiedInterfaces方法确是Spring AOP中比较重要的方法,也给了我们一个入手观察Spring AOP真正实现过程的一个突破口;我认为这个,才是AopProxyUtils给我们的价值;

AopContext

这个工具类就更简单,它代表AOP的上下文。主要是提供我们访问上下文中当前AOP对象的快速方法。

代码语言:javascript
复制
public abstract class AopContext {
	// 一个ThreadLocal,和当前上下文绑定的AOP对象
	private static final ThreadLocal<Object> currentProxy = new NamedThreadLocal<>("Current AOP proxy");

	// public方法,调用者可以在任何地方获取到当前上下文中的AOP代理对象。
	// 请注意:这个和exposeProxy参数有关,只有为true了才生效,默认都是false的
	public static Object currentProxy() throws IllegalStateException {
		Object proxy = currentProxy.get();
		if (proxy == null) {
			throw new IllegalStateException(
					"Cannot find current proxy: Set 'exposeProxy' property on Advised to 'true' to make it available.");
		}
		return proxy;
	}

	@Nullable
	static Object setCurrentProxy(@Nullable Object proxy) {
		Object old = currentProxy.get();
		if (proxy != null) {
			currentProxy.set(proxy);
		}
		else {
			currentProxy.remove();
		}
		return old;
	}
}

备注:这个工具类主要是和属性exposeProxy相关,让我们能够快捷的获取到AOP代理对象,而不是this对象。这个在事务不生效原因大解读的博文了得到了应用

AutoProxyUtils

为自动代理组件准备的工具类。主要用于框架内部使用(AbstractAutoProxyCreator

代码语言:javascript
复制
public abstract class AutoProxyUtils {

	// org.springframework.aop.framework.autoproxy.AutoProxyUtils.preserveTargetClass
	// preserve:保护的  保留的
	// determine:查明  测定
	public static final String PRESERVE_TARGET_CLASS_ATTRIBUTE =
			Conventions.getQualifiedAttributeName(AutoProxyUtils.class, "preserveTargetClass");
	// org.springframework.aop.framework.autoproxy.AutoProxyUtils.originalTargetClass
	public static final String ORIGINAL_TARGET_CLASS_ATTRIBUTE =
			Conventions.getQualifiedAttributeName(AutoProxyUtils.class, "originalTargetClass");


	// 判断该beanName是否应该被代理
	// `AbstractAutoProxyCreator`里就有判断是否能够被代理。  如果能够被代理,那就采用CGLIB的代理方式了
	// 往里setAttr,目前只有`ConfigurationClassPostProcessor`对config配置类进行增强的时候
	// 
	public static boolean shouldProxyTargetClass(ConfigurableListableBeanFactory beanFactory, @Nullable String beanName) {
		// 容器内存在这个Bean,并且这个Bean的定义信息里面属性值`PRESERVE_TARGET_CLASS_ATTRIBUTE`必须是true才行  说明才能被代理
		if (beanName != null && beanFactory.containsBeanDefinition(beanName)) {
			BeanDefinition bd = beanFactory.getBeanDefinition(beanName);
			return Boolean.TRUE.equals(bd.getAttribute(PRESERVE_TARGET_CLASS_ATTRIBUTE));
		}
		return false;
	}

	// 看看这个Bean定义的TargetClass
	// 如果Bean定义信息里面有ORIGINAL_TARGET_CLASS_ATTRIBUTE这个字段,那就不用getType()了
	// 以及ScopedProxyUtils创建和Scope有关的代理类的时候,其余地方都不会设置此属性
	@Nullable
	public static Class<?> determineTargetClass(ConfigurableListableBeanFactory beanFactory, @Nullable String beanName) {
		if (beanName == null) {
			return null;
		}
		if (beanFactory.containsBeanDefinition(beanName)) {
			BeanDefinition bd = beanFactory.getMergedBeanDefinition(beanName);
			Class<?> targetClass = (Class<?>) bd.getAttribute(ORIGINAL_TARGET_CLASS_ATTRIBUTE);
			if (targetClass != null) {
				return targetClass;
			}
		}
		return beanFactory.getType(beanName);
	}

	//Expose the given target class for the specified bean, if possible
	// 就是在它的Bean定义信息里面,设置一个ORIGINAL_TARGET_CLASS_ATTRIBUTE属性,然后吧targetClass类型放进去
	// 也是子啊`AbstractAutoProxyCreator`创建代理的时候会这只进去的
	static void exposeTargetClass(ConfigurableListableBeanFactory beanFactory, @Nullable String beanName,
			Class<?> targetClass) {

		if (beanName != null && beanFactory.containsBeanDefinition(beanName)) {
			beanFactory.getMergedBeanDefinition(beanName).setAttribute(ORIGINAL_TARGET_CLASS_ATTRIBUTE, targetClass);
		}
	}

}
AspectJAopUtils

相比于AopUtilsAspectJAopUtils是专门针对于AspectJ advisors的工具类。(当然AspectJ也是当下的主流方式)

代码语言:javascript
复制
public abstract class AspectJAopUtils {

	//拿到AspectJ的优先信息:AspectJPrecedenceInformation 这个就接口保存着
	@Nullable
	public static AspectJPrecedenceInformation getAspectJPrecedenceInformationFor(Advisor anAdvisor) {
		if (anAdvisor instanceof AspectJPrecedenceInformation) {
			return (AspectJPrecedenceInformation) anAdvisor;
		}
		Advice advice = anAdvisor.getAdvice();
		if (advice instanceof AspectJPrecedenceInformation) {
			return (AspectJPrecedenceInformation) advice;
		}
		return null;
	}

	// Advisor 是否是前置通知类型~~~~(Advisor都持有一个advice嘛)
	public static boolean isBeforeAdvice(Advisor anAdvisor) {
		AspectJPrecedenceInformation precedenceInfo = getAspectJPrecedenceInformationFor(anAdvisor);
		if (precedenceInfo != null) {
			return precedenceInfo.isBeforeAdvice();
		}
		return (anAdvisor.getAdvice() instanceof BeforeAdvice);
	}

	// Advisor 是否是后置通知类型~~~~(Advisor都持有一个advice嘛)
	public static boolean isAfterAdvice(Advisor anAdvisor) {
		AspectJPrecedenceInformation precedenceInfo = getAspectJPrecedenceInformationFor(anAdvisor);
		if (precedenceInfo != null) {
			return precedenceInfo.isAfterAdvice();
		}
		return (anAdvisor.getAdvice() instanceof AfterAdvice);
	}

}
AspectJProxyUtils

同样的,它相对于AopProxyUtils,它只是专门处理AspectJ代理对象的工具类。

代码语言:javascript
复制
public abstract class AspectJProxyUtils {

	// 判断,该Advisor是否是AspectJ的的增强器
	private static boolean isAspectJAdvice(Advisor advisor) {
		return (advisor instanceof InstantiationModelAwarePointcutAdvisor ||
				advisor.getAdvice() instanceof AbstractAspectJAdvice ||
				(advisor instanceof PointcutAdvisor &&
						 ((PointcutAdvisor) advisor).getPointcut() instanceof AspectJExpressionPointcut));
	}

	// 只提供这么一个公共方法,但是这个方法都还是非常重要的。 Capable:有能力的
	// 它在自动代理创建器`AspectJAwareAdvisorAutoProxyCreator#extendAdvisors`方法中有调用(重要~~~)
	// 在AspectJProxyFactory#addAdvisorsFromAspectInstanceFactory方法中也有调用
	// 它的作用:只要发现有AspectJ的Advisor存在,并且advisors还不包含有ExposeInvocationInterceptor.ADVISOR  那就在第一个位置上调添加一个ExposeInvocationInterceptor.ADVISOR
	// 这个`ExposeInvocationInterceptor.ADVISOR`的作用:就是获取到当前的currentInvocation,也是使用的ThreadLocal
	public static boolean makeAdvisorChainAspectJCapableIfNecessary(List<Advisor> advisors) {
		// Don't add advisors to an empty list; may indicate that proxying is just not required
		if (!advisors.isEmpty()) {
			boolean foundAspectJAdvice = false;
			for (Advisor advisor : advisors) {
				// Be careful not to get the Advice without a guard, as
				// this might eagerly instantiate a non-singleton AspectJ aspect
				if (isAspectJAdvice(advisor)) {
					foundAspectJAdvice = true;
				}
			}
			if (foundAspectJAdvice && !advisors.contains(ExposeInvocationInterceptor.ADVISOR)) {
				advisors.add(0, ExposeInvocationInterceptor.ADVISOR);
				return true;
			}
		}
		return false;
	}

}
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2019年04月20日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • Spring AOP工具类盘点
    • AopUtils
      • AopConfigUtils
        • AopNamespaceUtils
          • AopProxyUtils
            • AopContext
              • AutoProxyUtils
                • AspectJAopUtils
                  • AspectJProxyUtils
                  相关产品与服务
                  云顾问
                  云顾问(Tencent Cloud Smart Advisor)是一款提供可视化云架构IDE和多个ITOM领域垂直应用的云上治理平台,以“一个平台,多个应用”为产品理念,依托腾讯云海量运维专家经验,助您打造卓越架构,实现便捷、灵活的一站式云上治理。
                  领券
                  问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档