0
点赞
收藏
分享

微信扫一扫

Spring】Spring中AOP解析 中 AOP的具体实现

3.ProxyFactoryBean 代理工厂Bean 生产代理类

首先 在Spring中,如果一个类实现了FactoryBean 接口,最终放到容器中的bean是getObject返回的对象

因此,可以通过ProxyFactoryBean 代理工厂bean,创建一个bean的代理类放到容器中

1.案例演示一 new 对象与通知:

配置类

@Configuration
public class MyProxyFactoryBeanConf {

    @Bean
    public Object proxyBean()
    {
        //创建代理工厂bean对象
        ProxyFactoryBean proxyFactoryBean = new ProxyFactoryBean();
        //设置代理类
        proxyFactoryBean.setTarget(new CGLB_Target());
        //添加通知
        proxyFactoryBean.addAdvice(new MyAfterReturnAdvice());
        
        return proxyFactoryBean;
    }

}

启动类

public class AppTest {

    public static void main(String[] args) {

        AnnotationConfigApplicationContext app = new AnnotationConfigApplicationContext(MyProxyFactoryBeanConf.class);
        CGLB_Target bean = app.getBean(CGLB_Target.class);
        bean.say();
    }

}

2.案例演示二 容器中获取目标对象与通知

都已经使用SpringIOC容器了,还new 多过时

@Configuration
public class MyProxyFactoryBeanConf {

    //被代理的bean
    @Bean(name = "targetBean")
    public TargetBean createBean()
    {
        return new TargetBean();
    }

    @Bean(name = "myBeforeAdvice")
    public MyBeforeAdvice createAdvice()
    {
        return new MyBeforeAdvice();
    }

    @Bean(name = "proxyBean")
    public Object proxyBean()
    {
        //创建代理工厂bean对象
        ProxyFactoryBean proxyFactoryBean = new ProxyFactoryBean();
        //设置代理类
        proxyFactoryBean.setTargetName("targetBean");
        //添加通知
        proxyFactoryBean.setInterceptorNames("myBeforeAdvice");

        //返回代理对象
        return proxyFactoryBean;
    }


启动类

public class AppTest {

    public static void main(String[] args) {

        AnnotationConfigApplicationContext app = new AnnotationConfigApplicationContext(MyProxyFactoryBeanConf.class);
        TargetBean bean = app.getBean("proxyBean",TargetBean.class);
        bean.say();

    }

}

这里注意了,默认容器中有两个类型为TargetBean的bean,一个是普通bean,一个是代理bean

输出结果

image-20220406210232616

3.ProxyFactoryBean源码解析

一.new 对象与通知是如何生效的

`ProxyFactoryBean实现了FactoryBean接口,因此最终放到容器中bean应该是重写getObject方法返回的对象

image-20220406204420315

重写的getObject方法

image-20220406204550924

isSingleton()  默认是true

进 getSingletonInstance() 方法

image-20220406204745300

先看 createAopProxy() 方法

image-20220406204904054

image-20220406204947703

判断后决定是用CGLB生成代理类还是使用JDK动态代理

image-20220406205131012

二 容器中获取目标对象与通知是如何生效的

image-20220406210705320

设置为 ProxyFactoryBean 的两个属性值 其中 interceptorNames 是一个字符串数组

image-20220406210725155

看它的initializeAdvisorChain()方法

image-20220406211545665

遍历所有的拦截器BeanName,调用addGlobalAdvisors 方法

addGlobalAdvisors((ListableBeanFactory) this.beanFactory,
							name.substring(0, name.length() - GLOBAL_SUFFIX.length()));

从bean工厂中取出这个bean

image-20220406211734610

4.BeanNameAutoProxyCreator 根据beanName自动创建代理类

@Configuration
public class MyBeanNameAutoProxyCreator {

    //被代理的bean
    @Bean(name = "targetBean")
    public TargetBean createBean()
    {
        return new TargetBean();
    }

    @Bean(name = "myBeforeAdvice")
    public MyBeforeAdvice createAdvice()
    {
        return new MyBeforeAdvice();
    }

    @Bean(name = "proxyBean")
    public BeanNameAutoProxyCreator beanNameAutoProxyCreator()
    {
        BeanNameAutoProxyCreator beanNameAutoProxyCreator = new BeanNameAutoProxyCreator();
        //要代理的beanName  可以匹配
        beanNameAutoProxyCreator.setBeanNames("target*");
        //拦截器链  注意是有顺序的
        beanNameAutoProxyCreator.setInterceptorNames("myBeforeAdvice");
        return beanNameAutoProxyCreator;
    }
}

启动类

public class AppTest {

    public static void main(String[] args) {

        AnnotationConfigApplicationContext app = new AnnotationConfigApplicationContext(MyBeanNameAutoProxyCreator.class);
        TargetBean bean = app.getBean(TargetBean.class);
        bean.say();

    }

}

注意使用BeanNameAutoProxyCreator 不会创建两个bean,放到容器中的只有代理类

5.Spring的AOP实现

1.@EnableAspectJAutoProxy 开启切面自动代理功能

如果想使用AOP,我们需要在启动类上添加 @EnableAspectJAutoProxy 注解 所以从这个注解开始动刀

注意三个点

导入了一个 AspectJAutoProxyRegistrar 注册组件

@Import(AspectJAutoProxyRegistrar.class)
boolean proxyTargetClass() default false;   //是否使用CGLB创建代理对象
boolean exposeProxy() default false;  //是否将代理对象放入ThreadLocal ,如果为true,可以通过 AopContext 获取代理对象

image-20220407172625393

看 AspectJAutoProxyRegistrar 组件注册了什么 点进去

class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar

实现了 ImportBeanDefinitionRegistrar 接口 ,看重写的 registerBeanDefinitions 方法

image-20220407173555722

注册了AnnotationAwareAspectJAutoProxyCreator

看下 AnnotationAwareAspectJAutoProxyCreator 是什么

org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator

发现 AnnotationAwareAspectJAutoProxyCreator 继承了 BeanPostProcessor 后置处理器 那么,也就是说SpringIOC初始化每一个bean后,都会执行这个BeanPostProcessor 的实现类 ,而postProcessAfterInitialization的重写方法 在 org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator中

image-20220407174010313

2.AbstractAutoProxyCreator的bean初始化后处理

1.执行bean后置处理器的postProcessAfterInitialization方法

image-20220407175004088

2.过滤无需进行AOP的bean

首先看

Object cacheKey = getCacheKey(bean.getClass(), beanName);

image-20220407180051597

image-20220407180246001

跟进

wrapIfNecessary(bean, beanName, cacheKey)

image-20220407180541891

`Advice Pointcut Advisor AopInfrastructureBean 这四种类型的bean直接返回原对象,不需要进行AOP

image-20220407180652476

` shouldSkip() 方法留给程序员决定那些bean不需要AOP

image-20220407180931716

image-20220407180939761

如下面这个bean 将不会被AOP代理

@Component(value = "com.sgg.proxy.bean.MyBean.ORIGINAL")
public class MyBean {

    @MyAop
    public void method()
    {
        System.out.println("方法执行了");
    }

}

3.找到所有的advice

1.先找常规的 advice 的 子类

image-20220407183406217

接下来我们看 getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null) 这个方法

跟进来到 org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator.getAdvicesAndAdvisorsForBean

image-20220407183538809

跟进 findEligibleAdvisors(beanClass, beanName) 方法

image-20220407183728843

先看 findCandidateAdvisors() 是怎么拿到所有的advice的

跟进来到 org.springframework.aop.framework.autoproxy.BeanFactoryAdvisorRetrievalHelper.findAdvisorBeans()

image-20220407183946284

跟进

BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
      this.beanFactory, Advisor.class, true, false)

注意方法的四个参数

image-20220407184237301

拿到所有类型为 Advisor 的beanName 注意只是名字 如果有父容器,也取出父容器中的实现了Advisor 接口的bean的Name

image-20220407184314220

拿到所有的beanName后,遍历,

image-20220407184552822

判断是不是正在创建中,如果正在创建中,跳过 然后调用 this.beanFactory.getBean(name, Advisor.class) 获取(没有就创建bean),放到集合List advisors 中然后返回 至此,拿到了Spring容器中所有的advisor的子类

2.切面类的advisor

回到org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator.findCandidateAdvisors

通常我们都是使用@Aspect定义一个切面类,这种就需要通过this.aspectJAdvisorsBuilder.buildAspectJAdvisors()去找

image-20220407191627391

this.aspectJAdvisorsBuilder.buildAspectJAdvisors()

从容器中取出所有类型为Object的bean 也就是取出所有的bean

image-20220407191758870

拿到class,判断是否有@Aspect注解

image-20220407192059106

image-20220407192141474

调用 List classAdvisors = this.advisorFactory.getAdvisors(factory) 方法 拿到不同的advisor

首先找到类中所有非定义切入点的方法

image-20220407192714738

image-20220407192734857

看adviceMethodFilter过滤器

image-20220407192803150

如果注解类型是PointCut,返回null

回到getAdvisors方法,拿到所有的非@PonitCut的方法后

image-20220407192914987

调用 getAdvisor(method, lazySingletonAspectInstanceFactory, 0, aspectName) 创建 advisor

image-20220407193115624

至此,所有的advisor查找完毕 进行下一步过滤操作

4.按Class类型和方法名匹配符合条件的advisor

回到 findEligibleAdvisors 方法 看如何筛选的image-20220407185050346

跟进 image-20220407185142494

是不是实现了 IntroductionAdvisor 接口,然后调用 canApply(candidate, clazz) 判断是否能应用

image-20220407185527734

跟进canApply(candidate, clazz) 方法

如果当前advisor 是属于 IntroductionAdvisor ,按Class过滤

image-20220407185808726

如果当前advisor 是属于 PointcutAdvisor

调用 canApply(pca.getPointcut(), targetClass, hasIntroductions) 方法

image-20220407190237756

image-20220407190252760

与当前正在创建的bean匹配的advisor最终都存到了List eligibleAdvisors 中

image-20220407193703695

查找所有的advisor与过滤筛选完成后,进行代理类的创建

5.创建代理类

回到 org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.wrapIfNecessary 方法

image-20220407194010933

拿到所有的advice的流程已经走完,接下来就是创建代理类了,画张图,整理下流程

创建代理类的过程,请阅下篇博文

举报

相关推荐

0 条评论