spring的AOP(五)—-Spring AOP 编程(AspectJ )详解编程语言
AspectJ 简介
AspectJ是一个面向切面的框架,它扩展了Java语言。AspectJ定义了AOP语法所以它有一个专门的编译器用来生成遵守Java字节编码规范的Class文件。
AspectJ是一个基于Java语言的AOP框架
Spring2.0以后新增了对AspectJ切点表达式支持
@AspectJ 是AspectJ1.5新增功能,通过JDK5注解技术,允许直接在Bean类中定义切面
新版本Spring框架,建议使用AspectJ方式来开发AOP
使用AspectJ 需要导入Spring AOP和 AspectJ相关jar包
spring-aop-3.2.0.RELEASE.jar
com.springsource.org.aopalliance-1.0.0.jar
spring-aspects-3.2.0.RELEASE.jar
com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar
在配置文件中,引入 aop 的schema约束
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" 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" /beans
AspectJ 框架定义 Advice 增强类型 (六种 )
AspectJ 在传统AOP 的advice类型基础上,扩展了一种新的类型
1.Before 前置通知,相当于BeforeAdvice
2.AfterReturning 后置通知,相当于AfterReturningAdvice
3.Around 环绕通知,相当于MethodInterceptor
4.AfterThrowing 抛出通知,相当于ThrowAdvice
5.After 最终final通知,不管是否异常,该通知都会执行,这种增强是 AOP联盟规范中不存在的 。在异常发生时,后置通知 无法执行,因为后置通知在方法返回之后,才能执行 ,发生异常,方法无法返回 。最终通知,相当于代码 finally 代码块,目标方法有没有错误,必须执行
6.DeclareParents 引介通知,相当于IntroductionInterceptor
所有AspectJ 增强,内部都可以传入 JoinPoint 连接点对象,通过该对象 可以获得拦截了哪个类哪个方法
代码示例:
OrderDao.java
package com.my.aspectj; //订单接口 public interface OrderDao { public int save(); public void update(); public void delete(); public void search();
OrderDaoImpl.java
package com.my.aspectj; //被代理目标对象 public class OrderDaoImpl implements OrderDao { @Override public int save() { System.out.println("添加订单"); return 10; @Override public void update() { System.out.println("更新订单"); @Override public void delete() { System.out.println("删除订单"); int d = 1/0; @Override public void search() { System.out.println("查询订单");
MyAspect.java
package com.my.aspectj; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.ProceedingJoinPoint; //自定义 切面类 (在切面类当中 定义增强的方法) public class MyAspect { // 前置增强 public void before(JoinPoint joinPoint){ System.out.println("前置增强 ....." + joinPoint.toShortString()); // 后置增强 public void afterReturning(JoinPoint joinPoint, Object returnValue){ System.out.println("后置增强...."+ joinPoint.toShortString() + ", 方法返回值:" + returnValue); // 环绕增强 (控制目标方法执行,该方法具有返回值) // ProceedingJoinPoint对象可以控制目标方法执行 public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable{ System.out.println("环绕前增强...."); Object result = proceedingJoinPoint.proceed(); System.out.println("环绕后增强...."); return null; // 抛出增强 (扑捉目标异常) Throwable对象是固定的 public void afterThrowing(JoinPoint joinPoint, Throwable throwable){ System.out.println(joinPoint.toShortString() + "目标方法出现异常.... 原因:" + throwable.getMessage()); // 最终通知 public void after(JoinPoint joinPoint){ System.out.println("最终增强..... 用于释放资源 ....");
applicationContext.xml
?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" 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" !-- AspectJ AOP 开发案例 -- !-- 目标对象 -- bean id="orderDao" / !-- 切面对象 -- bean id="myAspect" /bean !-- 进行AOP配置 -- !-- 默认 有接口 使用 JDK代理,没有接口 使用 Cglib代理 -- aop:config proxy-target- !-- 整合AspectJ 框架的切面,含有多个切点和多个通知 -- aop:aspect ref="myAspect" !-- 引用自定义切面类 -- !-- 定义切点 -- aop:pointcut expression="execution(* com.my.aspectj.OrderDaoImpl.s*(..))" id="myAspectPointcut1"/ aop:pointcut expression="execution(* com.my.aspectj.OrderDaoImpl.delete(..))" id="myAspectPointcut2"/ !-- 定义通知 -- aop:before method="before" pointcut-ref="myAspectPointcut1"/ aop:after-returning method="afterReturning" pointcut-ref="myAspectPointcut1" returning="returnValue"/ aop:around method="around" pointcut-ref="myAspectPointcut1"/ aop:after-throwing method="afterThrowing" pointcut-ref="myAspectPointcut2" throwing="throwable"/ aop:after method="after" pointcut-ref="myAspectPointcut2"/ /aop:aspect /aop:config /beans
Test.java
package com.my.aspectj; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations="classpath:applicationContext.xml") public class Test { @Autowired @Qualifier("orderDao") private OrderDao orderDao; @org.junit.Test public void demo(){ orderDao.search(); orderDao.save(); orderDao.update(); orderDao.delete();
运行结果:
使用注解开发AspectJ 实现 AOP编程
在applicationContext.xml 引入 aop名称名称,加入以下配置开启AspectJ自动代理
aop:aspectj-autoproxy /
注解的作用:
@AspectJ 提供注解
@Aspect 定义切面
@Before 前置通知
@AfterReturning 后置通知
@Around 环绕通知
@AfterThrowing 异常通知
@After 最终通知
@Pointcut 定义切点
代码示例:
UserService.java
package com.my.annotation_aspectj; public interface UserService { public void save(); public int update(); public void delete(); public void select();
UserServiceImpl.java
package com.my.annotation_aspectj; public class UserServiceImpl implements UserService { @Override public void save() { System.out.println("添加用户"); @Override public int update() { System.out.println("修改用户"); return 0; @Override public void delete() { System.out.println("删除用户"); int[] arr = {}; System.out.println(arr[0]); @Override public void select() { System.out.println("查询用户");
MyAspect.java
package com.my.annotation_aspectj; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.After; import org.aspectj.lang.annotation.AfterReturning; import org.aspectj.lang.annotation.AfterThrowing; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.aspectj.lang.annotation.Pointcut; //使用注解定义切面信息 @Aspect public class MyAspect { // 前置增强 @Before(value="execution(* com.my.annotation_aspectj.UserServiceImpl.save(..))") // 这里value可以写切点表达式 或者 切点对象调用 public void before(JoinPoint joinPoint){ System.out.println("前置增强...." + joinPoint.toShortString()); // 后置增强 // returning 用来指定返回值参数名称 @AfterReturning(value="execution(* com.my.annotation_aspectj.UserServiceImpl.update(..))", returning="returnVal") public void afterReturning(JoinPoint joinPoint, Object returnVal){ System.out.println("后置增强...." + joinPoint.toShortString() + ", 方法返回值:" + returnVal); // 环绕增强 @Around(value="execution(* com.my.annotation_aspectj.UserServiceImpl.s*(..))") public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable{ System.out.println("环绕前增强..."); Object result = proceedingJoinPoint.proceed(); // 执行目标方法 System.out.println("环绕后增强..."); return result; // 抛出增强 @AfterThrowing(value="mypointcut()", throwing="throwable") // 使用 throwing 参数,指定异常对象传入参数名称 public void afterThrowing(JoinPoint joinPoint , Throwable throwable){ System.out.println(joinPoint.toShortString()+"目标方法发生异常,原因:"+ throwable.getMessage()); // 最终增强 @After(value="mypointcut()||mypointcut2()") public void after(JoinPoint joinPoint){ System.out.println("最终增强...."); // 单独定义一个切点 @Pointcut(value="execution(* com.my.annotation_aspectj.UserServiceImpl.delete(..))") private void mypointcut(){} // 方法名就是切点名 @Pointcut(value="execution(* com.my.annotation_aspectj.UserServiceImpl.save(..))") private void mypointcut2(){}
applicationContext.xml
?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" 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" !-- 开启AspectJ自动代理-- aop:aspectj-autoproxy / !-- 自动读取切面类中注解信息,完成切面拦截代理 -- !-- 目标 -- bean id="userService" / !-- 切面 -- bean id="myAspect" /bean /beans
Test.java
package com.my.annotation_aspectj; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations="classpath:applicationContext.xml") public class Test { @Autowired @Qualifier("userService") private UserService userService; @org.junit.Test public void demo(){ userService.select(); userService.save(); userService.delete(); userService.update();
相关文章
- spring容器初始化过程总结_java构造方法初始化
- Spring学习笔记(七)——SpringMVC常用的注解
- Spring batch教程 之 spring batch简介
- 理解 Spring ApplicationListener
- 是时候为Spring Boot 3.0做准备了
- spring官方文档 中文_Spring软件
- spring-boot:The following method did not exist: com.google.gson.GsonBuilder.setLenient()
- 关于Spring的两三事:如何控制Bean的加载顺序
- spring是什么意思_什么spring是孩子
- Spring AOP:面向切面编程的利器
- Spring Boot的性能优化(三)
- Spring Boot应用中引入Zuul-示例
- Spring Cloud Gateway 过滤器的作用(二)
- Spring Cloud Stream的概念和优势
- Spring Cloud Security的核心组件-Cloud OAuth2 Client示例
- Spring Cloud Task 高级特性Task Events
- Spring基于注解实现事务管理
- Spring错误:org.mybatis.spring.MyBatisSystemException: nested exception is org.apache.ibatis.binding.B详解编程语言
- 如何通俗的理解spring的控制反转、依赖注入、面向切面编程等等详解编程语言
- spring Boot(十九):使用Spring Boot Actuator监控应用详解编程语言
- Spring AOP(面向切面编程)是什么?
- Spring Boot 2.x :通过 spring-boot-starter-hbase 集成 HBase