动态代理,对业务方法的代理,将方法解耦
- 基于接口的:自带的Proxy,该方案是基于接口的,所以被代理类至少实现一个接口,最终也会返回该接口类型的对象。代理将拦截被代理对象的任何方法,最后用代理对象去执行业务对象的方法。
- 基于子类的:第三方提供cglib,被代理类不需实现接口。
AOP使用动态代理技术实现,主要是对已有方法的增强。
- Joinpoint(连接点):业务方法
- Pointcut(切入点):被增强的业务方法
- Advice(通知/增强):代理方法中的一些方法
前置通知:
切入点业务方法:不去修改的方法
后置通知:
异常通知:catch
最终通知:finally
环绕通知:手动控制通知何时执行增强代码的方案 - Introduction(引介):在不修改类的情况下,在运行期间为类动态添加一些方法和field
- Target(目标对象):被代理的对象,是对象
- Weaving(织入):把增强代码和目标对象结合来创建代理对象的过程
- Proxy(代理):创建的新代理对象
- Aspect(切面):切入点和通知的结合
使用AOP
- 导入需要的aop jar包
- 在配置文件中添加约束
- 将通知也配置到bean中
- 使用aop:config标签开始AOP的配置
- 使用用aop:aspect配置切面
- 使用aop:befor配置前置通知
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
<!--配置业务层-->
<bean id="accountService" class="spring.service.impl.AccountServiceImpl"></bean>
<!-- 通知类-->
<bean id="logger" class="spring.utils.Logger"></bean>
<aop:config>
<aop:aspect id="logAdvice" ref="logger">
<aop:before method="beforePrintLog"
pointcut="execution(public void spring.service.impl.AccountServiceImpl.saveAccount()))">
</aop:before>
</aop:aspect>
</aop:config>
</beans>
pointcut
切入点表达式的写法
- 全匹配:精准定位到单个方法,
public void spring.service.impl.AccountServiceImpl.saveAccount()
访问修饰符。 public
可以省略;- 返回类型可以用
*
表示; - 包名/类名/方法名/参数类型都可以用
*
表示; - 包名可使用
..
表示当前包或其子包; - 参数列表:基本类型直接写类型名称,引用类型必须是
包名.类名
的方式,参数列表可以使用..
表示有无参数都可。 - 可以使用
<aop:pointcut>
标签写到aop:aspect前
通知类型
<aop:befor />
<aop:after-returning />
<aop:after-throwing />
<aop:after />
<aop:around />
:切入点手动写到增强的代码中
使用注解配置
@Aspect
:将当前类配置为切面@Pointcut()
:切入点@Befor()
@AfterReturning()
@AfterThrowing()
@After()
@Around()
@EnableAspectJAutoProxy
XML中使用<aop:aspectj-autoproxy />
开启AOP注解