zl程序教程

您现在的位置是:首页 >  后端

当前栏目

Spring AOP源码分析(七)ProxyFactoryBean介绍

Spring源码AOP 分析 介绍
2023-09-14 08:59:44 时间
这篇文章里面就要说说Spring自己的AOP,搞清楚哪种方式是Spring自己实现的AOP,哪种方式是Spring引入aspectj的AOP。 
Spring自己的AOP实现在于ProxyFactoryBean。先看下使用案例(仍和之前的案例是一样的):接口AService、实现类AServiceImpl、通知MyBeforeAdvice 
?
No qualifying bean of type [com.lg.aop.service.AService] is defined: expected single matching bean but found 2: aServiceImpl,org.springframework.aop.framework.ProxyFactoryBean#0

原因就是对于接口AService,有两个实现类aServiceImpl和ProxyFactoryBean所生产的代理类。所以我们不能使用@Autowired(它是按类型注入),所以要使用按名称注入,我们怎么获取ProxyFactoryBean所产生的代理类的名称呢?其实就是ProxyFactoryBean配置的名称。因为ProxyFactoryBean实现了FactoryBean接口,对于这种接口从容器中获取该bean,不是获取的本身而是获取他的getObject方法所返回的值,看FactoryBean的文档: 
?

所以通过beanName找到了ProxyFactoryBean,然而不是返回该对象,而是返回他的getObject方法的返回值,所以我们通过ProxyFactoryBean的id就可以获取到它所产生的代理对象,所以更改如下: 
?

然后我们就要源码分析下这一过程,先看下是如何产生代理对象的,在ProxyFactoryBean的getObject方法中: 
?
                logger.warn("Using non-singleton proxies with singleton targets is often undesirable. " +
                        "Enable prototype proxies by setting the targetName property.");

重点1:就是根据我们配置的interceptorNames来获取对应的bean,并却转化成Advisor。如下: 
?
private synchronized void initializeAdvisorChain() throws AopConfigException, BeansException {
                throw new IllegalStateException("No BeanFactory available anymore (probably due to serialization) " +
                        "- cannot resolve interceptor names " + Arrays.asList(this.interceptorNames));
            // Globals cant be last unless we specified a targetSource using the property...
            if (this.interceptorNames[this.interceptorNames.length - 1].endsWith(GLOBAL_SUFFIX)
                    this.targetName == null this.targetSource == EMPTY_TARGET_SOURCE) {
                                "Can only use global advisors or interceptors with a ListableBeanFactory");
                            name.substring(0, name.length() - GLOBAL_SUFFIX.length()));
                        // Its a prototype Advice or Advisor: replace with a prototype.
                        // Avoid unnecessary creation of prototype bean just for advisor chain initialization.

this.advisorChainInitialized:标示是否已进行过初始化,若以初始化则不再进行初始化。然后就是将interceptorNames转化成Advisor。根据interceptorNames所包含的字符串到容器中进行查找,如果含有*则,则表示进行一定的匹配,符合的都会纳入。如官方文档中说的: 
?

这个包裹过程已经见过很多遍了,采用了适配器的模式。 
之后又是和其他的AOP方式接轨了,设置一些列要实现的接口和参数,使用DefaultAopProxyFactory先创建出AopProxy,要么是JdkDynamicAopProxy,要么是CglibAopProxy,然后就可以调用AopProxy的getProxy方法来获取代理对象了。这个过程详见上一篇博客http://lgbolgger.iteye.com/blog/2119810。 

这种方式实现的AOP还是比较麻烦的,同时配置一个ProxyFactoryBean仅能实现对一个目标对象的拦截,要想拦截多个目标对象,需要配置多个ProxyFactoryBean。所以大部分还是使用Spring引进的aspectj的AOP方式来进行AOP编程。 


Spring 源码阅读 62:基于 JDK 的 AOP 代理对特殊方法调用的处理 本文深入分析了 JdkDynamicAopProxy 的invoke方法的第一部分逻辑,也就是,对于哪些方法的调用,不对其进行增强,而是执行对应的特定逻辑,从中可以了解,Spring AOP 对哪些方法是默认不进行增强的。
Spring 源码阅读 61:基于 JDK 动态代理的 AOP 代理回调方法 invoke 分析 本文分析了 JdkDynamicAopProxy 的invoke方法,invoke方法是基于 JDK 动态代理创建的 AOP 代理对象的方法处理回调逻辑,也是 Spring AOP 增强目标方法的关键逻辑。
阿里特邀专家徐雷Java Spring Boot开发实战系列课程(第18讲):制作Java Docker镜像与推送到DockerHub和阿里云Docker仓库 立即下载