前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Spring5.0源码深度解析之SpringBean的Aop源码分析

Spring5.0源码深度解析之SpringBean的Aop源码分析

作者头像
须臾之余
发布2019-07-31 17:21:04
6430
发布2019-07-31 17:21:04
举报
文章被收录于专栏:须臾之余

SpringAop源码分析:需要关联SpringBean的生命周期

思考:

1.什么时候创建代理类对象 2.SpringAop中如何综合运用CGLIB和JDK动态代理

代码语言:javascript
复制
@EnableAspectJAutoProxy:开启AOP的权限

注入到Spring容器中

ImportBeanDefinitionRegistrar手动注册Bean对象

在前几章中提过,实现ImportBeanDefinitionRegistrar这个接口,可以自己手动注册一些Bean到Spring容器中

AspectJAutoProxyRegistrar实现了ImportBeanDefinitionRegistrar就可以手动注册Bean对象

代码语言:javascript
复制
class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {

   @Override
   public void registerBeanDefinitions(
         AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
       //这里手动注册Bean
      AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
      AnnotationAttributes enableAspectJAutoProxy =
            AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
      if (enableAspectJAutoProxy != null) {
         if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
            AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
         }
         if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
            AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
         }
      }
   }
}
代码语言:javascript
复制
AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
代码语言:javascript
复制
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry) {
    return registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry, (Object)null);
}
代码语言:javascript
复制
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry, @Nullable Object source) {
    return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
}
代码语言:javascript
复制
AnnotationAwareAspectJAutoProxyCreator.class
代码语言:javascript
复制
private static BeanDefinition registerOrEscalateApcAsRequired(Class<?> cls, BeanDefinitionRegistry registry, @Nullable Object source) {
    Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
    if (registry.containsBeanDefinition("org.springframework.aop.config.internalAutoProxyCreator")) {
        BeanDefinition apcDefinition = registry.getBeanDefinition("org.springframework.aop.config.internalAutoProxyCreator");
        if (!cls.getName().equals(apcDefinition.getBeanClassName())) {
            int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName());
            int requiredPriority = findPriorityForClass(cls);
            if (currentPriority < requiredPriority) {
                apcDefinition.setBeanClassName(cls.getName());
            }
        }
        return null;
    } else {
        RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
        beanDefinition.setSource(source);
        beanDefinition.getPropertyValues().add("order", -2147483648);
        beanDefinition.setRole(2);
        registry.registerBeanDefinition("org.springframework.aop.config.internalAutoProxyCreator", beanDefinition);//注册IOC容器中
        return beanDefinition;
    }
}

综上:总结下

1.@EnableAspectJAutoProxy:开启AOP的权限 2.@Import(AspectJAutoProxyRegistrar.class)注入到容器中,手动注册切面类 3.AnnotationAwareAspectJAutoProxyCreator需要将这个类注入到IOC容器中 4.registerBeanDefinition注册Bean信息内容: ##BeanId=org.springframework.aop.config.internalAutoProxyCreator ##class:AnnotationAwareAspectJAutoProxyCreator

我们打印下注册的Bean

1无参构造函数....说明对象初开始始化了 2执行自定义bean的init方法 beanDefinitionNames[i]:org.springframework.context.annotation.internalConfigurationAnnotationProcessor beanDefinitionNames[i]:org.springframework.context.annotation.internalAutowiredAnnotationProcessor beanDefinitionNames[i]:org.springframework.context.annotation.internalRequiredAnnotationProcessor beanDefinitionNames[i]:org.springframework.context.annotation.internalCommonAnnotationProcessor beanDefinitionNames[i]:org.springframework.context.event.internalEventListenerProcessor beanDefinitionNames[i]:org.springframework.context.event.internalEventListenerFactory beanDefinitionNames[i]:myConfig beanDefinitionNames[i]:memberServiceImpl beanDefinitionNames[i]:payService beanDefinitionNames[i]:loginAop beanDefinitionNames[i]:org.springframework.aop.config.internalAutoProxyCreator //这个就是我们注入的Bean

后面我们需要了解SpringAOP底层是如何实现的 离不开AnnotationAwareAspectJAutoProxyCreator

下面看看AnnotationAwareAspectJAutoProxyCreator类图结构

得出结论:AnnotationAwareAspectJAutoProxyCreator的祖宗是BeanPostProcessors

BeanPostProcessors是对我们的Bean的初始化方法实现增强。由Java多态,可知AnnotationAwareAspectJAutoProxyCreator也是可以实现对Bean初始化方法增强。

所以AnnotationAwareAspectJAutoProxyCreator本质就是对init方法实现增强

代码语言:javascript
复制
public interface BeanPostProcessor {
    @Nullable
    default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {//init方法前置处理
        return bean;
    }

    @Nullable
    default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {//init方法后置处理
        return bean;
    }
}

AnnotationAwareAspectJAutoProxyCreator的前置和后置在AbstractAutoProxyCreator实现类中实现

前置处理器:没做任何事

代码语言:javascript
复制
public Object postProcessBeforeInitialization(Object bean, String beanName) {
    return bean;
}

后置处理器:具体做事情,使用后置处理器实现代理对象的创建

代码语言:javascript
复制
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) throws BeansException {
    if (bean != null) {
        Object cacheKey = this.getCacheKey(bean.getClass(), beanName);
        if (!this.earlyProxyReferences.contains(cacheKey)) {
            return this.wrapIfNecessary(bean, beanName, cacheKey);
        }
    }
    return bean;
}

因为前置没做任何事情,我们可以debug到后置处理器,实现代理类对象的创建。

也就是任何Bean对象在初始化之前,都会调用AbstractAutoProxyCreator的后置处理创建代理类对象

代码语言:javascript
复制
if (mbd == null || !mbd.isSynthetic()) {
    wrappedBean = this.applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
代码语言:javascript
复制
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) throws BeansException {
    if (bean != null) {
        Object cacheKey = this.getCacheKey(bean.getClass(), beanName);
        if (!this.earlyProxyReferences.contains(cacheKey)) {
            return this.wrapIfNecessary(bean, beanName, cacheKey);
        }
    }
    return bean;
}

获得五个通知

创建代理类

代码语言:javascript
复制
public Object getProxy(@Nullable ClassLoader classLoader) {
    return this.createAopProxy().getProxy(classLoader);
}
代码语言:javascript
复制
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
    if (!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 {
            return (AopProxy)(!targetClass.isInterface() && !Proxy.isProxyClass(targetClass) ? new ObjenesisCglibAopProxy(config) : new JdkDynamicAopProxy(config));
        }
    }
}

总结:

被代理对象在初始化的时候,AbstractAutoProxyCreator 经过这样的一个类拦截。 判断该被代理对象是否有被有实现过接口,如果有实现过接口就使用jdk动态代理,如果没有实现接口则使用cglib动态代理。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

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

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

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

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档