AOP简介
AOP将业务模块与周边功能或者说为业务模块服务的功能区分开,例如:权限控制、日志统计。
AOP将这些共性的模块封装起来,减少了代码重复,降低了模块间的耦合度,更利于扩展与维护。
利用注解来开发AOP的步骤
1. 选择连接点
Spring是方法级别的AOP框架,所以需要选择某个方法作为连接点
....
public void service() {
// 仅仅只是实现了核心的业务功能
System.out.println("签合同");
System.out.println("收房租");
}
....
2.创建切面
在 Spring 中只要使用 @Aspect 注解一个类,那么 Spring IoC 容器就会认为这是一个切面了
package aspect;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;
@Component
@Aspect
class Broker {
@Before("execution(* pojo.Landlord.service())")
public void before(){
System.out.println("带租客看房");
System.out.println("谈价格");
}
@After("execution(* pojo.Landlord.service())")
public void after(){
System.out.println("交钥匙");
}
}
3. 定义切点
Spring 通过这个正则表达式判断具体要拦截的是哪一个类的哪一个方法
execution(* pojo.Landlord.service())
我们可以通过使用 @Pointcut 注解来定义一个切点
package aspect;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
@Component
@Aspect
class Broker {
@Pointcut("execution(* pojo.Landlord.service())")
public void lService() {
}
@Before("lService()")
public void before() {
System.out.println("带租客看房");
System.out.println("谈价格");
}
@After("lService()")
public void after() {
System.out.println("交钥匙");
}
}
环绕通知
它集成了前置通知和后置通知,它保留了连接点原有的方法的功能,所以它及强大又灵活
package aspect;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
@Component
@Aspect
class Broker {
// 注释掉之前的 @Before 和 @After 注解以及对应的方法
// @Before("execution(* pojo.Landlord.service())")
// public void before() {
// System.out.println("带租客看房");
// System.out.println("谈价格");
// }
//
// @After("execution(* pojo.Landlord.service())")
// public void after() {
// System.out.println("交钥匙");
// }
// 使用 @Around 注解来同时完成前置和后置通知
@Around("execution(* pojo.Landlord.service())")
public void around(ProceedingJoinPoint joinPoint) {
System.out.println("带租客看房");
System.out.println("谈价格");
try {
joinPoint.proceed();
} catch (Throwable throwable) {
throwable.printStackTrace();
}
System.out.println("交钥匙");
}
}