Aop自动创建代理对象的原理
我们在使用Spring Aop时,通常Spring会自动为我们创建目标bean的代理对象,以使用对应的Advisor
。前提是我们在使用Spring Aop时是使用的<aop:config/>
或<aop:aspectj-autoproxy/>
,这是因为当我们在applicationContext.xml文件中通过<aop:config/>
的形式定义需要使用Aop的场景时,Spring会自动为我们添加AspectjAwareAdvisorAutoProxyCreator
类型的bean;而我们定义了<aop:aspectj-autoproxy/>
时,Spring会默认为我们添加AnnotationAwareAspectjAutoProxyCreator
类型的bean。Spring中在bean实例化后能够对bean对象进行包装的是BeanPostProcessor
,AspectjAwareAdvisorAutoProxyCreator
和AnnotationAwareAspectjAutoProxyCreator
都是实现了BeanPostProcessor
接口的。AnnotationAwareAspectjAutoProxyCreator
的父类是AspectjAwareAdvisorAutoProxyCreator
,而AspectjAwareAdvisorAutoProxyCreator
的父类是AbstractAdvisorAutoProxyCreator
,AbstractAdvisorAutoProxyCreator
的父类是实现了BeanPostProcessor
接口的AbstractAutoProxyCreator
。它们的核心逻辑都是在bean初始化后找出bean容器中所有的能够匹配当前bean的Advisor
,找到了则将找到的Advisor
通过ProxyFactory
创建该bean的代理对象返回。AspectjAwareAdvisorAutoProxyCreator
在寻找候选的Advisor
时会找到bean容器中所有的实现了Advisor
接口的bean,而AnnotationAwareAspectjAutoProxyCreator
则在AspectjAwareAdvisorAutoProxyCreator
的基础上增加了对标注了@Aspect
的bean的处理,会附加上通过@Aspect
标注的bean中隐式定义的Advisor
。所以这也是为什么我们在使用@Aspect
标注形式的Spring Aop时需要在applicationContext.xml文件中添加<aop:aspectj-autoproxy/>
。既然AspectjAwareAdvisorAutoProxyCreator
和AnnotationAwareAspectjAutoProxyCreator
都会自动扫描bean容器中的Advisor
,所以当我们使用了<aop:config/>
或<aop:aspectj-autoproxy/>
形式的Aop定义时,如果因为某些原因光通过配置满足不了你Aop的需求,而需要自己实现Advisor
接口时(一般是实现PointcutAdvisor接口
),那这时候你只需要把自己的Advisor
实现类,定义为Spring的一个bean即可。如果你在applicationContext.xml中没有定义<aop:config/>
或<aop:aspectj-autoproxy/>
,那你也可以直接在applicationContext.xml中直接定义AspectjAwareAdvisorAutoProxyCreator
或AnnotationAwareAspectjAutoProxyCreator
类型的bean,效果也是一样的。其实为了能够在创建目标bean的时候能够自动创建基于我们自定义的Advisor
实现类的代理对象,我们的bean容器中只要有AbstractAutoProxyCreator
类型的bean定义即可,当然了你实现自己的BeanPostProcessor
,在其postProcessAfterInitialization
方法中创建自己的代理对象也是可以的。但是本着不重复发明轮子的原则,我们尽量使用官方已经提供好的实现即可。AbstractAutoProxyCreator
是继承自ProxyConfig
的,所以我们在定义AbstractAutoProxyCreator
子类的bean时,我们也可以手动的定义一些ProxyConfig
中包含的属性,比如proxyTargetClass
、exposeProxy
等。AbstractAutoProxyCreator
的子类除了AspectjAwareAdvisorAutoProxyCreator
和AnnotationAwareAspectjAutoProxyCreator
外,我们可用的还有BeanNameAutoProxyCreator
和DefaultAdvisorAutoProxyCreator
。
BeanNameAutoProxyCreator
BeanNameAutoProxyCreator
可以用来定义哪些bean可与哪些Advisor/Advice
绑定,以生成对应的代理对象。需要绑定的bean是通过beanNames
属性来指定的,对应的是bean的名称,其中可以包含“*”号,表示任意字符,比如“abc*”则匹配任意名称以“abc”开始的bean;需要绑定的Advisor/Advice
是通过interceptorNames
来指定的,如果指定的是Advisor
,那么是否可生成基于该Advisor
的代理需要对应的bean能够匹配对应Advisor
(PointcutAdvisor
类型)的Pointcut
;如果指定的是Advice
,则该Advice
会被包含在Pointcut
恒匹配的Advisor
中,即能够与所有的bean绑定生成对应的代理,且会对所有的方法调用起作用。 指定interceptorNames时是不能使用通配符的,只能精确的指定需要应用的Advisor/Advice
对应的bean名称。
<bean id="userService" class="com.elim.learn.spring.aop.service.UserServiceImpl"/>
<bean id="myService" class="com.elim.learn.spring.aop.service.MyService"/>
<bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
<!-- 匹配userService和所有名称以my开头的bean -->
<property name="beanNames" value="userService, my*"/>
<!-- interceptorNames中不能使用通配符,只能是精确匹配,
即精确指定Advisor/Advice的bean名称 -->
<property name="interceptorNames" value="logBeforeAdvice, myAdvisor "/>
</bean>
<bean id="logBeforeAdvice"
class="com.elim.learn.spring.aop.advice.LogBeforeAdvice" />
<bean id="myAdvisor" class="com.elim.learn.spring.aop.advisor.MyAdvisor"/>
如上就是一个使用BeanNameAutoProxyCreator
建立指定的bean基于指定的Advisor/Advice
的代理对象的示例。示例中我们指定interceptorNames时特意应用了一个Advisor
实现和一个Advice
实现。Advice
会应用于所有绑定的bean的所有方法调用,而Advisor
只会应用于其中的Pointcut能够匹配的方法调用。这里的源码我就不提供了,有兴趣的朋友可以自己试试。
DefaultAdvisorAutoProxyCreator
DefaultAdvisorAutoProxyCreator
的父类也是AbstractAdvisorAutoProxyCreator
。DefaultAdvisorAutoProxyCreator
的作用是会默认将bean容器中所有的Advisor
都取到,如果有能够匹配某一个bean的Advisor
存在,则会基于能够匹配该bean的所有Advisor
创建对应的代理对象。需要注意的是DefaultAdvisorAutoProxyCreator
在创建bean的代理对象时是不会考虑Advice
的,只是Advisor
。如上面的示例中,如果我们希望所有的bean都能够自动的与匹配的Advisor
进行绑定生成对应的代理对象,那么我们可以调整配置如下。
<bean id="userService" class="com.elim.learn.spring.aop.service.UserServiceImpl"/>
<bean id="myService" class="com.elim.learn.spring.aop.service.MyService"/>
<bean
class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"/>
<bean id="myAdvisor" class="com.elim.learn.spring.aop.advisor.MyAdvisor"/>
使用DefaultAdvisorAutoProxyCreator
时可能我们并不希望为所有的bean定义都自动应用bean容器中的所有Advisor
,而只是希望自动创建基于部分Advisor
的代理对象。这个时候如果我们期望应用自动代理的Advisor
的bean定义的名称都是拥有固定的前缀时,则我们可以应用DefaultAdvisorAutoProxyCreator
的setAdvisorBeanNamePrefix(String)
指定需要应用的Advisor
的bean名称的前缀,同时需要通过setUsePrefix(boolean)
指定需要应用这种前缀匹配机制。如我们的bean容器中有两个Advisor
定义,一个bean名称是“myAdvisor”,一个bean名称是“youAdvisor”,如果只期望自动创建基于bean名称以“my”开始的Advisor的代理,则可以进行如下配置。
<bean
class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator">
<property name="usePrefix" value="true" />
<!-- 匹配所有bean名称以my开始的Advisor -->
<property name="advisorBeanNamePrefix" value="my" />
</bean>
(注:本文是基于Spring4.1.0所写,Elim写于2017年5月12日)
相关推荐
在 Spring AOP 的自动代理创建过程中,`AbstractAutoProxyCreator` 类起着关键作用。它实现了 `BeanPostProcessor` 接口,会在 Bean 初始化后对其进行处理,生成代理对象。`AbstractAutoProxyCreator` 会查找 Spring...
在Spring AOP的源码中,`org.springframework.aop.framework.ProxyFactoryBean`是创建代理的主要类,它会根据目标类是否有接口选择JDK动态代理或CGLIB。`org.aopalliance.intercept.MethodInterceptor`接口定义了...
当目标对象没有实现接口时,Spring会自动选择CGLIB作为默认的代理方式。 在Spring Boot项目中,配置和使用AOP相对简单。首先,我们需要引入Spring AOP和AspectJ的依赖,这通常在pom.xml或build.gradle文件中完成。...
现在,我们回到主题——"springaop依赖的jar包"。在Spring 2.5.6版本中,使用Spring AOP通常需要以下核心jar包: - `spring-aop.jar`:这是Spring AOP的核心库,包含了AOP相关的类和接口。 - `spring-beans.jar`:...
5. **自动代理(Auto Proxy)**:Spring AOP默认使用Java动态代理或CGLIB生成代理对象,以便在调用目标方法时插入通知。 案例中的"Spring_2_AOP"可能包含了以下内容: - 示例代码展示了如何定义一个切面,包括通知...
最后,值得注意的是,对于源码探索,可以查看Spring AOP的相关源代码,如`org.springframework.aop.config.AopNamespaceUtils`,了解其内部是如何解析XML配置并创建对应的AOP代理对象的。对于工具的使用,Spring提供...
"spring-aop-jar"这个主题涉及到Spring框架中的核心组件之一——Spring AOP。这里我们将深入探讨Spring AOP、相关jar文件以及它们在实际开发中的作用。 首先,我们来看一下提供的文件: 1. aopalliance.jar:这是一...
Java动态代理是Java编程中一个重要的特性,它允许在运行时创建代理对象,这些代理对象可以作为原有对象的代理,实现在调用方法时添加额外的功能。Spring AOP(面向切面编程)正是利用了这一特性来实现其核心功能——...
Spring框架是Java开发中不可或缺的一部分,它通过提供两种核心特性——控制反转(IoC)和面向切面编程(AOP)来简化应用的构建。理解并掌握这两种技术对于任何Java开发者来说都至关重要。 **控制反转(IoC)**,也...
"9Spring AOP 盗梦空间之四——Around"这个标题暗示我们将深入探讨Spring AOP中的一个关键概念——环绕通知(Around Advice)。环绕通知是Spring AOP中功能最全面的通知类型,它提供了对方法执行前、执行后以及异常...
1. **AOP代理**:Spring AOP支持两种代理方式,即JDK动态代理和CGLIB代理。JDK代理用于实现接口的类,而CGLIB代理则用于未实现接口的类。spring-aop.jar包含了这些代理机制的相关类,如`org.springframework.aop....
本篇文章将深入探讨如何使用Spring AOP实现性能监控器,并通过源码分析来理解其工作原理。 首先,我们要了解AOP的核心概念——切面(Aspect)、通知(Advice)、连接点(Join Point)、切入点(Pointcut)和织入...
这样,Spring容器会自动扫描并代理匹配的切面类,使得通知能够正确地织入到目标方法中。 在实际项目中,@AspectJ可以帮助我们更优雅地处理横切关注点,减少代码冗余,提高代码结构的清晰度。配合Spring的其他特性,...
当应用启动时,Spring容器会自动检测所有定义的切面并创建相应的代理对象。代理对象在被调用时,会根据切入点判断是否需要执行通知。这个过程是由`org.springframework.aop.framework.adapter....
3. **设置代理**:Spring AOP会根据切点和通知创建代理对象。当调用代理对象的方法时,实际上会执行通知中的逻辑。 4. **集成Oracle权限**:在通知中,我们需要查询Oracle数据库以获取用户的角色和权限。这可能涉及...
5. **运行与测试**:在MyEclipse中,你可以创建一个测试类来调用被AOP代理的`UserService`方法,观察日志记录是否按预期工作。 在压缩包`SpringAOPDemo1`中,很可能包含了整个Spring AOP的示例代码,包括`...
Spring AOP主要通过动态代理机制实现,根据目标对象是否实现了接口,它会使用JDK动态代理或CGLIB代理。当目标对象是接口类型时,Spring会使用JDK的Proxy类生成一个实现了该接口的代理对象;若目标对象没有接口,...
在这个名为"springAOP-dome"的实例中,我们将探讨如何利用Spring AOP实现一个简单的日志记录功能,以作为入门学习。 首先,了解AOP的基本概念是必要的。面向切面编程是一种编程范式,旨在解决程序中的横切关注点,...
在Spring配置文件中,需要启用AOP代理: ```xml <aop:aspectj-autoproxy /> ``` 或者在Spring Boot项目中,由于已经默认启用,无需额外配置。 ### 6. 总结 Spring AOP使得我们可以将关注点分离,提升代码的...
4. **Spring AOP的代理创建过程** - 首先,Spring容器会识别出需要代理的对象,这些对象通常带有特定的注解(如`@Component`)或配置(如`<bean>`标签)。 - 然后,根据目标对象是否实现接口,Spring决定使用JDK...