博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【Spring AOP】AspectJ开发
阅读量:319 次
发布时间:2019-03-04

本文共 7317 字,大约阅读时间需要 24 分钟。


文章目录


AspectJ 开发

① AOP 操作准备 — AspectJ

Spring框架一般都是基于AspectJ实现AOP操作


☞ What is AspectJ?

  • AspectJ 不是 Spring 组成部分,属于独立 AOP 框架,一般把 AspectJ 和 Spirng 框架一起使用,进行 AOP 操作


☞ How to use it?

  • 基于AspectJ实现AOP操作的方式:
    • 基于xml配置文件方式
    • 基于注解方式


☞ FirstStep~

  • 在项目工程里面引入 AOP 相关依赖
    在这里插入图片描述


☞ Simple Learning

☛ 切入点表达式

     1.作用:明确对哪个类里面的哪个方法进行增强

     2.语法结构:execution( [权限修饰符] [返回类型] [类全路径] [方法名称]([参数列表]) )

举例 1:对 com.atguigu.dao.BookDao 类里面的 add 进行增强      execution(* com.atguigu.dao.BookDao.add(..))      举例 2:对 com.atguigu.dao.BookDao 类里面的所有的方法进行增强      execution(* com.atguigu.dao.BookDao.* (..))举例 3:对 com.atguigu.dao 包里面所有类,类里面所有方法进行增强      execution(* com.atguigu.dao.*.* (..))


② AspectJ 基于注解方式操作实现AOP

1、创建类,在类里面定义方法

package AspectJ.anno;import org.springframework.stereotype.Component;/** * 被增强的类 */public class User {
public void add(){
System.out.println("add......"); }}


2、创建增强类(编写增强逻辑)

package AspectJ.anno;/** * 增强的类 */public class UserProxy {
// 前置通知 public void before(){
System.out.println("before......"); }}


3、进行通知的配置

(1)在 spring 配置文件中,开启注解扫描

(2)使用注解创建 User 和 UserProxy 对象

package AspectJ.anno;import org.springframework.stereotype.Component;/** * 被增强的类 */@Component  // 添加注解创建对象public class User {
public void add(){
System.out.println("add......"); }}package AspectJ.anno;import org.aspectj.lang.annotation.Aspect;import org.aspectj.lang.annotation.Before;import org.springframework.stereotype.Component;/** * 增强的类 */@Component // 添加注解创建对象public class UserProxy {
// 前置通知 public void before(){
System.out.println("before......"); }}

(3)在增强类上面添加注解 @Aspect

package AspectJ.anno;import org.aspectj.lang.annotation.Aspect;import org.aspectj.lang.annotation.Before;import org.springframework.stereotype.Component;/** * 增强的类 */@Component // 添加注解创建对象@Aspect    // 生成代理对象public class UserProxy {
// 前置通知 public void before(){
System.out.println("before......"); }}

(4)在 spring 配置文件中开启生成代理对象


4、配置不同类型的通知

(1)在增强类的里面,在作为通知方法上面添加通知类型注解,使用切入点表达式配置

package AspectJ.anno;import org.aspectj.lang.ProceedingJoinPoint;import org.aspectj.lang.annotation.*;import org.springframework.stereotype.Component;/** * 增强的类 */@Component // 添加注解创建对象@Aspect    // 生成代理对象public class UserProxy {
// 前置通知 // 添加前置通知注解 --- 指定切入点表达式(明确要被增强的方法) @Before(value = "execution(* AspectJ.anno.User.add(..))") public void before() {
System.out.println("before......"); } //后置通知(返回通知) @AfterReturning(value = "execution(* AspectJ.anno.User.add(..))") public void afterReturning() {
System.out.println("afterReturning........."); } //最终通知 @After(value = "execution(* AspectJ.anno.User.add(..))") public void after() {
System.out.println("after........."); } //异常通知 @AfterThrowing(value = "execution(* AspectJ.anno.User.add(..))") public void afterThrowing() {
System.out.println("afterThrowing........."); } //环绕通知 @Around(value = "execution(* AspectJ.anno.User.add(..))") public void around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
System.out.println("环绕之前........."); //被增强的方法执行 proceedingJoinPoint.proceed(); System.out.println("环绕之后........."); }}

注意:Around环绕通知是在被增强方法执行前、后都执行,所以被增强的方法在这之间执行,需要利用proceedingJoinPoint.proceed();来完成!!!


(2)测试

public class test {
@Test public void test_anno(){
try {
// 加载配置文件 ApplicationContext context = new ClassPathXmlApplicationContext("AspectJ/bean_anno.xml"); // 获取对象 User user = context.getBean("user", User.class); // 条用add方法 user.add(); } catch (Exception e){
e.printStackTrace(); } }}

通过结果我们可以理清这五种通知的执行顺序。注意After、AfterReturing两种通知的区别,After是在被增强的方法执行后就立刻执行,AfterReturning是在返回值之后立刻执行。

在这里插入图片描述
还有AfterThrowing是在被增强的方法有异常抛出之后立即执行。可以看到在add方法中抛出异常之后,AfterThrowing执行,并且之后的所有通知均被阻断
在这里插入图片描述


5、相同的切入点抽取

比如上述的五种通知中我们使用的通知切入点表达式完全一样,针对这种情况,我们可以对其进行抽取。在类中定义一个方法(方法名称自定义),然后只需要在该方法上添加@Pointcut注解,value属性填写公共切入点表达式,然后在需要用到的注释value属性值中填写该方法名称即可

/** * 增强的类 */@Component // 添加注解创建对象@Aspect    // 生成代理对象public class UserProxy {
// 定义公共切入点抽取方法 @Pointcut(value = "execution(* AspectJ.anno.User.add(..))") public void same_point(){
} // 前置通知 // 添加前置通知注解 --- 指定切入点表达式(明确要被增强的方法) @Before(value = "same_point()") public void before() {
System.out.println("before......"); } //后置通知(返回通知) @AfterReturning(value = "same_point()") public void afterReturning() {
System.out.println("afterReturning........."); } //最终通知 @After(value = "same_point()") public void after() {
System.out.println("after........."); } //异常通知 @AfterThrowing(value = "same_point()") public void afterThrowing() {
System.out.println("afterThrowing........."); } //环绕通知 @Around(value = "same_point()") public void around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
System.out.println("环绕之前........."); //被增强的方法执行 proceedingJoinPoint.proceed(); System.out.println("环绕之后........."); }}

结果保持不变~

在这里插入图片描述


6、有多个增强类多同一个方法进行增强,设置增强类优先级

假设StudentProxy类也同时对User类中的add()方法进行增强:

  • 方法:在增强类上面添加注解 @Order(数字类型值)数字类型值越小优先级越高
package AspectJ.anno;import org.aspectj.lang.annotation.*;import org.springframework.core.annotation.Order;import org.springframework.stereotype.Component;@Component@Aspect@Order(value = 1)public class StudentProxy {
@Pointcut(value = "execution(* AspectJ.anno.User.add(..))") public void point(){
} @Before(value = "point()") public void before(){
System.out.println("Student Before ,........"); } //最终通知 @After(value = "point()") public void after() {
System.out.println("Student After........."); } //后置通知(返回通知) @AfterReturning(value = "point()") public void afterReturning() {
System.out.println("Student afterReturning........."); }}

通过结果我们可以看出每种通知的先后执行顺序都是相对于单个增强类的内部顺序而言的当有多个类增强一个方法时,只有当级别大的(优先级低的)执行完毕后,级别小的(优先级高的)才会继续执行

在这里插入图片描述


③ AspectJ 基于xml配置文件方式操作实现AOP

1.创建两个类,增强类和被增强类,创建方法

package AspectJ.xml;/** * 被增强的类 */public class People {
public void eating(){
System.out.println("eating......"); }}package AspectJ.xml;/** * 增强类 */public class PeopleProxy {
public void before(){
System.out.println("before......."); }}


2.在Spring配置文件中创建两个类对象


3.在Spring配置文件中共配置切入点

  • 使用aop:config标签进行aop增强;
  • 之前是通过注解的方式配置切入点,在xml配置文件中,采用aop:pointcut标签来实现,其属性expression中填入切入点表达式;
  • 具体的增强方法在配置前首先要通过aop:aspect标签实现切面的配置(将通知应用到切入点的过程 — 将增强逻辑代码写入到需要增强的方法的过程),然后在切面中通过各种通知实现增强)。

在这里插入图片描述


4.测试

@Test public void test_xml(){
try {
// 加载配置文件 ApplicationContext context = new ClassPathXmlApplicationContext("AspectJ/bean_xml.xml"); // 获取对象 People people = context.getBean("people", People.class); // 条用add方法 people.eating(); } catch (Exception e){
e.printStackTrace(); } }

通过测试运行,可以看出通过xml方式,AspectJ实现了AOP操作~

在这里插入图片描述


转载地址:http://cbeq.baihongyu.com/

你可能感兴趣的文章