AOP简介
AOP (Aspect Orient Programming),直译过来就是 面向切面编程。AOP 是一种编程思想,是面向对象编程(OOP)的一种补充。面向对象编程将程序抽象成各个层次的对象,而面向切面编程是将程序抽象成各个切面,是Spring的核心思想之一。
AOP实现
Spring中的aop是通过动态代理实现的,那么他具体是如何实现的呢?Spring通过一个切面类,在他的类上加入@Aspect 注解,定义一个Pointcut方法,最后定义一系列的增强方法。这样就完成一个对象的切面操作。
使用注解实现Spring AOP
Spring AOP通知类型
- @Before:前置通知,在目标方法执行之前运行的通知,但不能阻止执行流继续到连接点(除非抛出异常)
- @AfterReturning:返回后通知,在目标方法正常返回之后运行的通知(即一个方法正常返回而且没有抛出异常)
- @AfterThrowing:抛出异常后通知,在目标方法通过抛出异常退出,则运行AfterThrowing通知
- @After:后置通知,在目标方法运行结束之后,不管目标是否正常退出或者异常返回都将运行的通知
- @Around:环绕通知,环绕目标方法的通知,环绕通知可以在方法调用之前和之后执行自定义行为
AOP注解
- @Aspect:作用是把当前类标识为一个切面供容器读取
- @Pointcut:切入点,可以定义表达式或者方法签名
- @EnableAspectJAutoProxy:用于开启Spring Aop注解的功能
service接口类
public interface TestService {
void test();
}
service实现类将实现类注入到Spring容器中
@Service
public class TestServiceImpl implements TestService {
@Override
public void test() {
System.out.println("TestService的Test()方法执行");
}
}
创建一个controller其中把service类注入到controller中,同时把controller注册到ioc容器中
@Component("TestController")
public class TestController {
@Autowired
private TestService testService;
public void Test(){
testService.test();
}
}
定义一个切面类并且注册到ioc容器中
切入点表达式看你项目实现类的package
//切面类
@Aspect
@Component
public class TestAspect {
//定义切入点
@Pointcut("execution(* com.example.springaop.service.impl..*.*(..))")
private void pointcut(){
}
//环绕通知
@Around("pointcut()")
//ProceedingJoinPoint 连接点对象
public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Exception {
//获取签名
Signature signature = proceedingJoinPoint.getSignature();
//获取目标方法名称
String methodName = signature.getName();
System.out.println("开始执行环绕通知,方法名称"+ methodName);
try{
long startTime = System.currentTimeMillis();
//执行实现类test方法
Object proceed = proceedingJoinPoint.proceed();
long endTime = System.currentTimeMillis();
System.out.println(methodName + "方法耗时:" + (endTime - startTime) + "毫秒");
return proceed;
}catch (Throwable throwable){
throwable.printStackTrace();
throw new Exception("方法异常");
}
}
//前置通知
@Before("pointcut()")
public void before(JoinPoint joinpoint){
String methodName = joinpoint.getSignature().getName();
System.out.println("开始执行前置通知,方法名称"+ methodName);
}
//后置通知
@After("pointcut()")
public void after(JoinPoint joinPoint){
String methodName = joinPoint.getSignature().getName();
System.out.println("开始执行后置通知,方法名称"+ methodName);
}
//返回通知
@AfterReturning("pointcut()")
public void afterReturning(JoinPoint joinPoint){
String methodName = joinPoint.getSignature().getName();
System.out.println("开始执行后置返回通知,方法名称"+ methodName);
}
//异常通知
@AfterThrowing("pointcut()")
public void afterThrowing(JoinPoint joinPoint){
String methodName = joinPoint.getSignature().getName();
System.out.println("开始执行抛出异常返回通知,方法名称"+ methodName);
}
}
定义一个aop config配置类
@Configuration
//开启Aop注解
@EnableAspectJAutoProxy
@ComponentScan("com.example.springaop")
public class AopConfig {
}
测试运行
@Test
void contextLoads() {
AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(AopConfig.class);
TestController testController = (TestController) annotationConfigApplicationContext.getBean("TestController");
testController.Test();
}
模拟异常情况