我们要弄明白,spring aop是什么?怎么用?实现原理?
参考Spring AOP详细介绍 AOP(Aspect Oriented Programming)面向切面编程。面向切面,是与OOP(Object Oriented Programming)面向对象编程并列的编程思想。 通过定义切面,可以让一些业务无关的代码,与业务代码相解耦。比如要在业务方法执行前后打印日志时,我们只需定义一个切面,而不用把打印日志的代码加到业务方法中,这样就将日志打印代码和业务代码相解耦了。 它有几个概念:Aspect(切面)、JointPoint(连接点)、Advice(通知)、Pointcut(切入点)、AOP代理。概念的详细解释见Spring - 通知(Advice)和Advisor(增强器/顾问)和Spring AOP详细介绍。 切面有两种实现:Advice(通知)、Advisor(增强器)。两种实现的区别其实都是将通知和切面进行了封装,原理基本上是一样的,只是使用的方式不同而已。详情可参考<aop:aspect>与<aop:advisor>的区别。
来自https://blog.csdn.net/q982151756/article/details/80513340
spring aop的切面有两种声明方式:xml、注解。任何一种声明方式下,你都可以定义Advice和Advisor。 一般人们喜欢用Advice做功能增强,用Advisor做事务管理。 要进一步了解,可参考[1]:
下图展示了spring aop在方法正常返回和抛出异常时,各个通知的执行顺序。
参考:
spring aop是用动态代理实现的。通过动态代理,可以对被代理对象的方法进行增强。 spring aop用到了两种动态代理技术:jdk动态代理、cglib库。
在用jdk动态代理对某个对象的方法增强时,这个方法一定要是实现自某个接口。jdk会生成一个继承该接口的代理对象,从而将代理对象上的接口方法调用都移交给InvocationHandler.invoke
。打个比方,假设有类关系如下:
上图中,我们可以用jdk动态代理对Student.say进行功能增强,但没法增强Student.walk。
我们可以用jdk动态代理在Student.say方法调用前后打印日志,因为Student.say继承自Person.say。jdk动态代理会生成Person接口的实现类对象,将其上的say方法调用都移交给InvocationHandler.invoke
。
但是,如果我们想对Student.walk增强,jdk动态代理就束手无策了。因为Student.walk方法不来自任何一个接口。就算我们生成了一个Person的实现类对象,它也无法调用walk方法,因为Person接口没有walk方法。而cglib可以做到这一点。cglib会生成一个继承Student类的代理对象,所有代理对象上调用的方法,都会移交给MethodInterceptor.intercept执行,进而我们可以对这个类里的所有方法进行功能增强(final方法除外,因为不能final方法被继承)。
所以,当要增强没有实现任何接口的方法时,Spring是使用CGlib实现的。
事务管理开启时 全局视角
@Autowired
注入时,才能进行代理设置。@Autowired
注入时,spring aop才能为原对象创建代理对象。 ↩