AOP_anno 注解方式aop
利用注解完成aop配置,首先要完成注解ioc注册Bean,然后再通知类中配置切面和各种通知类型,在给各个方法加上通知类型的注解后,需要设置切入点,利用@Pointcut
注解即可设置切入点,再让通知注解引用它。注解aop就完成了。
前期准备
-
首先pom导包:一个是spring核心包,另一个是用于解析切入点表达式和aop相关的包。
<dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.2.2.RELEASE</version> </dependency> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.9.5</version> </dependency> </dependencies>
-
bean.xml修改为aop和context空间, 因为除了aop还要 ioc注解功能。
<?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"> </beans>
配置
-
首先利用注解把业务层和通知层注册为Bean,和原来利用
Bean
标签效果一样@Service("accountService") public class AccountService implements IAccountService{...} //===== @Component("logger")//表示该类是Bean public class Logger{...}
-
配置bean.xml里扫描包,使注解生效
<context:component-scan base-package="com.chajiu"></context:component-scan>
-
开启aop服务
<!-- 开启 aop服务--> <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
-
配置通知层为切面类
@Component("logger")//表示该类是Bean @Aspect//表示当前类是个切面类 public class Logger{...}
-
为通知类的各个方法加上通知类型注解,表示对应的通知类型
@Before() public void logSt(){...} @AfterReturning() public void logEd(){...} @Around() public Object aroundLogger(ProceedingJoinPoint pjp){...}
-
但是切入点
pointcut
在哪里配置呢?利用@Pointcut
注解即可,使用一个方法名作为id
,切入点表达式和原来xml中pointcut
一样@Pointcut("execution(* com.chajiu.service.Impl.*.*(..))") public void p1(){};
-
让通知类型的注解使用该切入点,注意需要完整的
p1()
,不可缺括号//完整通知类代码 @Component("logger")//表示该类是Bean @Aspect//表示当前类是个切面类 public class Logger { @Pointcut("execution(* com.chajiu.service.Impl.*.*(..))") public void p1(){}; @Before("p1()") public void logSt(){ System.out.println("开始记录日志"); } @AfterReturning("p1()") public void logEd(){ System.out.println("结束记录日志"); } @Around("p1()") public Object aroundLogger(ProceedingJoinPoint pjp){ Object rtValue=null; try { Object[] args=pjp.getArgs(); System.out.println("环绕日志 前置"); rtValue=pjp.proceed(args); System.out.println("环绕日志 后置"); return rtValue; } catch (Throwable throwable) { System.out.println("环绕日志 异常"); throwable.printStackTrace(); }finally { System.out.println("环绕日志 最终"); } return rtValue; } }
测试
为了更清晰的看到结果,先注释掉了除了环绕通知外的别的通知。测试类内容和之前的无不同:
public class AOPtest {
public static void main(String[] args) {
ApplicationContext ac= new ClassPathXmlApplicationContext("bean.xml");
IAccountService accountService=(IAccountService) ac.getBean("accountService");
accountService.saveAccount();
}
}
结果
E:\jdk\bin\java.exe ...
环绕日志 前置
保存账户了
环绕日志 后置
环绕日志 最终
Process finished with exit code 0
网友评论