如何理解AOP中JDK代理实现的原理

发布时间:2021-10-09 14:05:54 作者:iii
来源:亿速云 阅读:175

本篇内容主要讲解“如何理解AOP中JDK代理实现的原理”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“如何理解AOP中JDK代理实现的原理”吧!

???? 动态代理

动态代理技术在Spring AOP中分为两种:

???? 基于JDK原生的动态代理.

提供一种在运行时创建一个实现了一组接口的新类由于Java是不支持实例化接口的,因此JDK会在运行期间生成一个代理类对给定的接口进行实现在调用该代理类接口的时候,将实现逻辑转发到调用处理器中(Invocation handler)


???? 基于CGLIB的动态代理.

CGLIB(Code Generation Library)是基于ASM(对Java字节码进行操作的框架)的类库

注意,由于是采用继承覆盖的方式,所以由final方法修饰的类无法使用CGLIB进行代理。


???? 前提小结


???? Spring的AOP实现原理

???? @EnableAspectJAutoProxy
???? 实现方案

@EnableAspectJAutoProxy注解正是通过@Import的方式来将 AspectJAutoProxyRegistrar类注册成Spring的Bean,以便在容器解析切面类时派上用场。那么AspectJAutoProxyRegistrar类的作用是什么?

@Import(AspectJAutoProxyRegistrar.class)
???? proxyTargetClass

@EnableAspectJAutoProxy支持处理标有AspectJ的@Aspect批注的组件,用户可以主动声明proxyTargetClass来指定Spring AOP使用哪种动态代理方式来创建代理类(默认使用基于实现接口的JDK动态代理方式)。

  @Configuration
  @EnableAspectJAutoProxy(proxyTargetClass=true)
  @ComponentScan("com.libo")
  public class AppConfig {
      // ...
  }
???? exposeProxy
???? AspectJAutoProxyRegistrar

通过@Import注册AspectJAutoProxyRegistrar,通常情况下,我们的启动类本身也是一个Bean,Spring支持使用 @Import来导入一个没有标记任何Spring注解 的类来将该Java类注册成Spring的Bean。

Registers an AnnotationAwareAspectJAutoProxyCreator against the current BeanDefinitionRegistry as appropriate based on a given @EnableAspectJAutoProxy annotation.

根据当前BeanDefinitionRegistry在适当的位置注册AnnotationAwareAspectJAutoProxyCreator。

如何理解AOP中JDK代理实现的原理

???? ImportBeanDefinitionRegistrar

AspectJAutoProxyRegistrar:实现了ImportBeanDefinitionRegistrar接口,用来注册AspectJAnnotationAutoProxyCreator,也就是支持注解驱动(同时兼容XML)解析的AspectJ自动代理创建器。

???? AspectJAutoProxyRegistrar源码分析
class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
    
	@Override
    public void registerBeanDefinitions(
         AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
         // 向容器注册AspectJAnnotationAutoProxyCreator
        AopConfigUtils.
		    registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
        AnnotationAttributes enableAspectJAutoProxy =
        AnnotationConfigUtils.attributesFor(importingClassMetadata,
													EnableAspectJAutoProxy.class);
        // 如果@EnableAspectJAutoProxy上存在标签内容
        if (enableAspectJAutoProxy != null) {
            // proxyTargetClass为true,则强制指定AutoProxyCreator使用CGLIB进行代理
            if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
                AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
            }
            // 是否开启exposeProxy特性
            if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
                AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
            }
        }
    }
}

AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);

org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader#loadBeanDefinitionsForConfigurationClass(configClass.getImportBeanDefinitionRegistrars())

这行代码,从代码的语义上我们可以大致可以猜出来,这是解析当前配置类上是否存在通过@Import导入的实现了ImportBeanDefinitionRegistrar的类

如何理解AOP中JDK代理实现的原理

最终会调用AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary方法,注册一个AnnotationAwareAspectJAutoProxyCreator,该类属于AOP的核心类。

???? registerBeanDefinitions

执行AspectJAutoProxyRegistrar#registerBeanDefinitions方法。

@Nullable
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(
        BeanDefinitionRegistry registry, @Nullable Object source) {
    return      registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
}
???? 查找切面

从上面的代码可以看出来AnnotationAwareAspectJAutoProxyCreator这个类作为实际操作者,查看该类的继承关系图。(省略一些不必要的类)。

如何理解AOP中JDK代理实现的原理

首先看第一个接口,BeanPostProcessor,这个接口作为顶层接口,肯定不会被外部直接调用,所以大概率是底下的几个具体实现类被调用,然后通过判断是不是InstantiationAwareBeanPostProcessor接口的类型,再执行相应逻辑,带着这个疑惑,来看源码。

???? AbstractAutoProxyCreator

AbstractAutoProxyCreator通过postProcessAfterInitialization实现AOP功能

   // 在实例化之后进行操作容器对象
    @Override
    public Object postProcessAfterInitialization(@Nullable Object bean, String 
		beanName) throws BeansException {
        if (bean != null) {
            Object cacheKey = getCacheKey(bean.getClass(), beanName);
            if (!this.earlyProxyReferences.contains(cacheKey)) {
                return wrapIfNecessary(bean, beanName, cacheKey);
            }
        }
        return bean;
    }

	protected Object wrapIfNecessary(Object bean, String beanName, Object 
		cacheKey) {
    // beanName不为空,并且存在于targetSourcedBeans中,也就是自定义的
	// TargetSource被解析过了
    if (StringUtils.hasLength(beanName) && 
		this.targetSourcedBeans.contains(beanName)) {
        return bean;
    }
    // 如果Bean为advisedBeans,也不需要被代理
    if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
        return bean;
    }
    // isInfrastructureClass和shouldSkip的作用:
    // 识别切面类,加载切面类成advisors
    // 为什么又执行一次是因为存在循环依赖的情况下无法加载advisor
    if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), 
		beanName)) {
        this.advisedBeans.put(cacheKey, Boolean.FALSE);
        return bean;
    }

    // Create proxy if we have advice.
    // 返回匹配当前Bean的所有Advice、Advisor、Interceptor
    Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), 
		beanName, null);
    if (specificInterceptors != DO_NOT_PROXY) {
        this.advisedBeans.put(cacheKey, Boolean.TRUE);
        // 创建Bean对应的代理,SingletonTargetSource用于封装实现类的信息
        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;
}
???? AbstractAdvisorAutoProxyCreator
    @Override
    @Nullable
    protected Object[] getAdvicesAndAdvisorsForBean(
            Class<?> beanClass, String beanName, @Nullable TargetSource 
			targetSource) {
        List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
        if (advisors.isEmpty()) {
            return DO_NOT_PROXY;
        }
        return advisors.toArray();
    }
	//这里调用了findEligibleAdvisors来寻找合适的advisors,如果返回的集合为空,那么    // 最后返回null.
   // 如果返回了advisors,将其数组化返回.

    protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String 
			beanName) {
        //BeanFactory 中所有 Advisor 的实现
        List<Advisor> candidateAdvisors = findCandidateAdvisors();
        // 有资格的 Advisor
        List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, 
		beanClass, beanName);
        extendAdvisors(eligibleAdvisors);
        if (!eligibleAdvisors.isEmpty()) {
            eligibleAdvisors = sortAdvisors(eligibleAdvisors);
        }
        return eligibleAdvisors;
    }
	
//首先获取之前解析过的advisors列表-candidateAdvisors,这里是所有的切面类解析成的advisors.
//在candidateAdvisors中找到当前Bean匹配的advisor-findAdvisorsThatCanApply.
//将获取到的eligibleAdvisors进行排序.

    protected List<Advisor> findCandidateAdvisors() {
        Assert.state(this.advisorRetrievalHelper != null, "No 
					 BeanFactoryAdvisorRetrievalHelper available");
        return this.advisorRetrievalHelper.findAdvisorBeans();
    }

    protected List<Advisor> findAdvisorsThatCanApply(
            List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) {
        	ProxyCreationContext.setCurrentProxiedBeanName(beanName);
			try {
				return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);
			}
			finally {
				ProxyCreationContext.setCurrentProxiedBeanName(null);
			}
    }
	
	public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> 	candidateAdvisors, Class<?> clazz) {
    if (candidateAdvisors.isEmpty()) {
        return candidateAdvisors;
    }
    // 存储最终匹配的Advisor集合
    List<Advisor> eligibleAdvisors = new ArrayList<>();
    for (Advisor candidate : candidateAdvisors) {
        // 当前advisor对象是否实现了IntroductionAdvisor接口
        if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) {
            eligibleAdvisors.add(candidate);
        }
    }
    boolean hasIntroductions = !eligibleAdvisors.isEmpty();
    for (Advisor candidate : candidateAdvisors) {
        if (candidate instanceof IntroductionAdvisor) {
            // already processed
            continue;
        }
        // canApply->判断当前的advisor的pointcut表达式是否匹配当前class
        if (canApply(candidate, clazz, hasIntroductions)) {
            eligibleAdvisors.add(candidate);
        }
    }
    return eligibleAdvisors;
}
	
	//最终是调用了AopUtils.findAdvisorsThatCanApply来筛选匹配Bean的Advisors.
???? 关于createProxy

ProxyFactory 对象中有要代理的bean和这个Bean上的advisor

Bean使用哪种代理

当Bean实现接口时,Spring就会用JDK的动态代理。 当Bean没有实现接口时,Spring会自动使用CGlib实现,但是前提是项目中导入了CGlib的相关依赖,否则Spring只能使用JDK来代理那些没有实现接口的类,这样生成的代理类会报错。 AopProxy有两个实现类JdkDynamicAopProxy和CglibAopProxy。都是构造 ReflectiveMethodInvocation.proceed()。

JdkDynamicAopProxy

invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
retVal = invocation.proceed();

CglibAopProxy

// CglibMethodInvocation 继承于 ReflectiveMethodInvocation
retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();

ReflectiveMethodInvocation.proceed()

public Object proceed() throws Throwable {
    // 当所有拦截器都执行后,调用目标类的目标方法
    if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
        return invokeJoinpoint();
    }

    Object interceptorOrInterceptionAdvice =
            this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
    if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
        // 动态拦截器
        InterceptorAndDynamicMethodMatcher dm =
                (InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
        if (dm.methodMatcher.matches(this.method, this.targetClass, this.arguments)) {
            return dm.interceptor.invoke(this);
        }
        else {
            // Dynamic matching failed.
            // Skip this interceptor and invoke the next in the chain.
            return proceed();
        }
    }
    else {
        // MethodInterceptor的实现类在处理完自己的逻辑后,还是会调用procee(),传入this就是为了达到这个目的
        return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
    }
}

Advisor

如何理解AOP中JDK代理实现的原理

Advice

如何理解AOP中JDK代理实现的原理

Joinpoint

如何理解AOP中JDK代理实现的原理


????AnnotationAwareAspectJAutoProxyCreator

Spring用来处理应用上下文中被@AspectJ注解标记的类的。继续进入registerOrEscalateApcAsRequired方法中看看注册流程.

org.springframework.aop.config.AopConfigUtils#registerOrEscalateApcAsRequired
private static BeanDefinition registerOrEscalateApcAsRequired(
        Class<?> cls, BeanDefinitionRegistry registry, @Nullable Object source) {
    Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
    // 当前容器是否包含 org.springframework.aop.config.internalAutoProxyCreator
    if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
        BeanDefinition apcDefinition = 
			registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
        if (!cls.getName().equals(apcDefinition.getBeanClassName())) {
            int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName());
            int requiredPriority = findPriorityForClass(cls);
            if (currentPriority < requiredPriority) {
                apcDefinition.setBeanClassName(cls.getName());
            }
        }
        return null;
    }
	
    // 将传入的class包装成BeanDefinition,然后注册到容器中,并讲其order的执行顺序
	//调整为最优。
    // 在aop中,这里会注册AnnotationAwareAspectJAutoProxyCreator.class这个类
    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;
}
  1. 首先查看当前容器中是否包含

org.springframework.aop.config.internalAutoProxyCreator的BeanDefiniton.

  1. 如果没有,将传入的class(在此处传入了AnnotationAwareAspectJAutoProxyCreator.class)包装成RootBeanDefinition,然后注册到容器中.

  2. 设置proxyTargetClass与exposeProxy

我们看一下如何设置proxyTargetClass即可,大体上设置proxyTargetClass与exposeProxy的逻辑都是相通的.

// 如果@EnableAspectJAutoProxy上存在标签内容
if (enableAspectJAutoProxy != null) {
    // 如果proxyTargetClass为true,则强制指定AutoProxyCreator使用CGLIB进行代理
    if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
        AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
    }
    // 是否开启exposeProxy特性
    if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
        AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
    }
}
进入AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);

AopConfigUtils#forceAutoProxyCreatorToUseClassProxying
public static void forceAutoProxyCreatorToUseClassProxying(BeanDefinitionRegistry registry) {  
    // 如果容器中包含 org.springframework.aop.config.internalAutoProxyCreator
    if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {  
        // 取出 org.springframework.aop.config.internalAutoProxyCreator的BeanDefinition
        BeanDefinition definition =     
		 registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);  
        // 设置proxyTargetClass为true
        definition.getPropertyValues().add("proxyTargetClass", Boolean.TRUE);
    }
}

简单理解 @ImportImportBeanDefinitionRegistrar,下面我们通过两个用例来理解@Import和ImportBeanDefinitionRegistrar

通过@Import导入类让Spring进行管理

public class NeedImportBean {
    public void doSomething(){
        Logger.getGlobal().info("Through @Import registry to a bean ");
    }
}

在启动类中将NeedImportBean导入

/**
 * @author jaymin
 * 2020/11/30 20:13
 */
@Configuration
@ComponentScan(value = "com.xjm")
@Import(NeedImportBean.class)
@EnableAspectJAutoProxy
public class ApplicationConfig {
    public static AnnotationConfigApplicationContext getApplicationContext() {
        return new AnnotationConfigApplicationContext(ApplicationConfig.class);
    }
}

//对NeedImportBean做getBean

public class BeanFactoryDemo {
    public static void main(String[] args) throws Exception {
        AnnotationConfigApplicationContext applicationContext = 
				ApplicationConfig.getApplicationContext();
               NeedImportBean needImportBean = 
			   applicationContext.getBean(NeedImportBean.class);
    }
}
???? 实现ImportBeanDefinitionRegistrar

NeedImportBean实现ImportBeanDefinitionRegistrar接口,然后验证两个点:

public class NeedImportBean implements ImportBeanDefinitionRegistrar{

    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        Logger.getGlobal().info("Through implements ImportBeanDefinitionRegistrar and @Import to callback me.");
    }

    public void doSomething(){
        Logger.getGlobal().info("Through @Import registry to a bean ");
    }

}

???? refresh

首先容器会加载refresh方法。

如何理解AOP中JDK代理实现的原理

如何理解AOP中JDK代理实现的原理

到此,相信大家对“如何理解AOP中JDK代理实现的原理”有了更深的了解,不妨来实际操作一番吧!这里是亿速云网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!

推荐阅读:
  1. Spring AOP的实现原理
  2. Spring AOP中JDK和CGLib动态代理哪个更快?

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

java spring aop

上一篇:rocketmq文档中物理部署结构和逻辑部署结构的概述以及特点

下一篇:如何配置3-WSL-SSH

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》