AOP在Spring中的作用
提供声明式事务,允许用户自定义切面
- 横切关注点:跨越应用程序多个模块的方法或功能。即是,与我们业务逻辑无关的,但是我们需要 关注的部分,就是横切关注点。如日志 , 安全 , 缓存 , 事务等等 ....
- 切面(ASPECT):横切关注点 被模块化 的特殊对象。即,它是一个类。
- 通知(Advice):切面必须要完成的工作。即,它是类中的一个方法。
- 目标(Target):被通知对象。
- 代理(Proxy):向目标对象应用通知之后创建的对象。
- 切入点(PointCut):切面通知 执行的 “地点”的定义。
- 连接点(JointPoint):与切入点匹配的执行点
SpringAOP中,通过Advice定义横切逻辑,Spring中支持5种类型的Advice
即 Aop 在 不改变原有代码的情况下 , 去增加新的功能 .
使用Spring实现AOP
需要导入一个依赖包
<!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.4</version>
</dependency>
方式一 通过Spring API实现
首先编写我们的业务接口和实现类
publicinterfaceUserService {
publicvoidadd();
publicvoiddelete();
publicvoidupdate();
publicvoidsearch();
}
publicclassUserServiceImplimplementsUserService{
@Override
publicvoidadd() {
System.out.println("增加用户");
}
@Override
publicvoiddelete() {
System.out.println("删除用户");
}
@Override
publicvoidupdate() {
System.out.println("更新用户");
}
@Override
publicvoidsearch() {
System.out.println("查询用户");
}
}
然后去写我们的增强类 , 我们编写两个 , 一个前置增强MethodBeforeAdvice 一个后置增强AfterReturningAdvice
publicclassLogimplementsMethodBeforeAdvice {
//method : 要执行的目标对象的方法
//objects : 被调用的方法的参数
//Object : 目标对象
@Override
publicvoidbefore(Methodmethod, Object[] objects, Objecto) throwsThrowable {
System.out.println( o.getClass().getName() +"的"+method.getName()
+"方法被执行了");
}
}
publicclassAfterLogimplementsAfterReturningAdvice {
//returnValue 返回值
//method被调用的方法
//args 被调用的方法的对象的参数
//target 被调用的目标对象
@Override
publicvoidafterReturning(ObjectreturnValue, Methodmethod, Object[] args, Objecttarget) throwsThrowable {
System.out.println("执行了"+target.getClass().getName()
+"的"+method.getName()+"方法,"
+"返回值:"+returnValue);
}
}
最后去spring的文件中注册 , 并实现aop切入实现 , 注意导入约束 .
<?xmlversion="1.0" encoding="UTF-8"?>
<beansxmlns="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">
<!--需要导入aop的约束--->
<!--注册bean-->
<beanid="userService"class="com.kuang.service.UserServiceImpl"/>
<beanid="log"class="com.kuang.log.Log"/>
<beanid="afterLog"class="com.kuang.log.AfterLog"/>
<!--aop的配置-->
<aop:config>
<!--切入点 expression:表达式匹配要执行的方法-->
<aop:pointcutid="pointcut"expression="execution(* com.kuang.service.UserServiceImpl.*(..))"/>
<!--返回值,类名,方法名,参数 ..代表可以有任意个参数-->
<!--执行环绕; advice-ref执行方法 . pointcut-ref切入点-->
<aop:advisoradvice-ref="log"pointcut-ref="pointcut"/>
<aop:advisoradvice-ref="afterLog"pointcut-ref="pointcut"/>
</aop:config>
</beans>
测试
publicclassMyTest {
@Test
publicvoidtest(){
ApplicationContextcontext=newClassPathXmlApplicationContext("beans.xml");
UserServiceuserService= (UserService)context.getBean("userService");
// 动态代理代理的是接口
userService.search();
}
}
Aop的重要性 : 很重要 . 一定要理解其中的思路 , 主要是思想的理解这一块 .
Spring的Aop就是将公共的业务 (日志 , 安全等) 和领域业务结合起来 , 当执行领域业务时 , 将会把公共业 务加进来 . 实现公共业务的重复利用 . 领域业务更纯粹 , 程序猿专注领域业务 , 其本质还是动态代理 .