Spring基于注解的AOP配置
操作步骤
-
配置spring创建容器时要扫描的包
-
对工具类和实现类加上注解
-
标注切面和切点
@Component("logger")
@Aspect// 表示当前类是一个切面
public class Logger {
@Pointcut("execution(* cn.luis.service.impl.*.*(..))")
private void pt() {}\
...
}
- 标注通知类型
- 配置spring开启注解AOP的支持
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
配置文件
<?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"
xmlns:context="http://www.springframework.org/schema/context"
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
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!-- 配置spring创建容器时要扫描的包-->
<context:component-scan base-package="cn.luis"></context:component-scan>
<!-- 配置spring开启注解AOP的支持 -->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
</beans>
四种常用通知
注意:此方式的通知存在执行顺序问题
账户的业务层实现类
@Service("accountService")
public class AccountServiceImpl implements IAccountService{
@Override
public void saveAccount() {
System.out.println("执行了保存");
//int i = 1/0;
}
}
记录日志的工具类
@Component("logger")
@Aspect// 表示当前类是一个切面
public class Logger {
@Pointcut("execution(* cn.luis.service.impl.*.*(..))")
private void pt() {}
/**
* 前置通知
*/
@Before("pt()")
public void beforePrintLog() {
System.out.println("前置通知开始记录日志...");
}
/**
* 后置通知
*/
@AfterReturning("pt()")
public void aftereReturnPrintLog() {
System.out.println("后置通知开始记录日志...");
}
/**
* 异常通知
*/
@AfterThrowing("pt()")
public void afterThrowingPrintLog() {
System.out.println("异常通知开始记录日志...");
}
/**
* 最终通知
*/
@After("pt()")
public void afterPrintLog() {
System.out.println("最终通知开始记录日志...");
}
}
测试类
public class AOPTest {
public static void main(String[] args) {
// 1.获取容器
ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
// 2.获取对象
IAccountService as = (IAccountService) ac.getBean("accountService");
// 3.执行方法
as.saveAccount();
}
}
结果:
- 存在执行顺序问题
前置通知开始记录日志...
执行了保存
最终通知开始记录日志...
后置通知开始记录日志...
环绕通知
账户的业务层实现类
@Service("accountService")
public class AccountServiceImpl implements IAccountService{
@Override
public void saveAccount() {
System.out.println("执行了保存");
//int i = 1/0;
}
}
记录日志的工具类
@Component("logger")
@Aspect// 表示当前类是一个切面
public class Logger {
@Pointcut("execution(* cn.luis.service.impl.*.*(..))")
private void pt() {}
@Around("pt()")
public Object aroundPrintLog(ProceedingJoinPoint pjp) {
Object rtValue = null;
try {
// 1.得到方法执行所需的参数
Object[] args = pjp.getArgs();
System.out.println("环绕通知开始记录日志...前置");
// 2.明确调用业务层方法(切入点方法),这里的异常要用 【throws Throwable】
rtValue = pjp.proceed(args);
System.out.println("环绕通知开始记录日志...后置");
// 3.返回值
return rtValue;
} catch (Throwable t) {
System.out.println("环绕通知开始记录日志...异常");
// 4.抛异常
throw new RuntimeException(t);
} finally {
System.out.println("环绕通知开始记录日志...最终");
}
}
}
测试类
public class AOPTest {
public static void main(String[] args) {
// 1.获取容器
ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
// 2.获取对象
IAccountService as = (IAccountService) ac.getBean("accountService");
// 3.执行方法
as.saveAccount();
}
}
结果:
- 无顺序问题
环绕通知开始记录日志...前置
执行了保存
环绕通知开始记录日志...后置
环绕通知开始记录日志...最终
不使用xml的配置方式
在src -- main -- java
下创建config
包,创建SpringConfiguration
类
在测试类中要修改容器
ApplicationContext ac = new AnnotationConfigApplicationContext(SpringConfiguration.class);
创建配置类
package config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
@Configuration //指定当前类为配置类
@ComponentScan("cn.luis") // 指定spring在创建容器时要扫描的包
@EnableAspectJAutoProxy // 开启注解AOP的支持
public class SpringConfiguration {
}
测试类
package cn.luis.test;
import cn.luis.service.IAccountService;
import config.SpringConfiguration;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class AOPTest {
public static void main(String[] args) {
// 1.获取容器
ApplicationContext ac = new AnnotationConfigApplicationContext(SpringConfiguration.class);
// 2.获取对象
IAccountService as = (IAccountService) ac.getBean("accountService");
// 3.执行方法
as.saveAccount();
}
}
结果:
环绕通知开始记录日志...前置
执行了保存
环绕通知开始记录日志...后置
环绕通知开始记录日志...最终