Spring框架(5)---AspectJ实现AOP

本文内容纲要:Spring框架(5)---AspectJ实现AOP

AspectJ实现AOP

上一篇文章Spring框架(4)---AOP讲解铺垫,讲了一些基础AOP理解性的东西,那么这篇文章真正开始讲解AOP

通过AspectJ实现AOP要比普通的实现Aop要方便的多,所以第五篇文章有关SpringAOP我暂且不写,后面整理好了再补充上;

那我们首先还是讲一些有的没的的东西:

什么是Spring的AspectJ的AOP

AspectJ是一个面向切面的框架,它扩展了Java语言。AspectJ定义了AOP语法所以它有一个专门的编译器用来生成遵守Java字节编码规范的Class文件。

  Spring2.0以后新增了对AspectJ切点表达式支持,@AspectJ 是AspectJ1.5新增功能,通过JDK5注解技术,允许直接在Bean类中定义切面

  新版本Spring框架,建议使用AspectJ方式来开发AOP

那我们先来一个小案例,还是以前面狗的案例举例:

1.导入相关架包

在原来的基础上导入下面四个架包:

  • spring-aop-4.2.0.RELEASE.jar
  • com.springsource.org.aopalliance-1.0.0.jar
  • spring-aspects-4.2.0.RELEASE.jar
  • com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar

2.编写配置文件applicationContext.xml 导入aop的命名空间

<?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:p="http://www.springframework.org/schema/p"

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/context http://www.springframework.org/schema/context/spring-context.xsd

http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"> <!-- bean definitions here -->

<!-- 配置注解bean所在的包 -->

<context:annotation-config/>

<context:component-scan base-package="com.study.spring.d_advisor"></context:component-scan>

<!-- 打开自动代理 -->

<aop:aspectj-autoproxy/>

</beans>

3.编写代理对象

1 public class Dog {

2

3 public void run() {

4 System.out.println("狗会跑");

5 }

6

7 public void jump() {

8

9 System.out.println("狗会跳");

10

11 }

12

13 public void eat() {

14

15 System.out.println("狗能吃");

16 }

17 }

4)编写切面类

import org.aspectj.lang.annotation.Aspect;

import org.aspectj.lang.annotation.Before;

//@Aspect声明当前类是一个切面

@Aspect

public class MyAspectJ {

//@Before代表在执行方法之前执行增强代码

@Before("execution(* com.study.dog.Dog.*(..))")

public void before1() {

System.out.println("饲养员叫你你猜能动");

}

}

5编写配置文件

<?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:p="http://www.springframework.org/schema/p"

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/context http://www.springframework.org/schema/context/spring-context.xsd

http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"> <!-- bean definitions here -->

<!-- 配置注解bean所在的包 -->

<context:annotation-config/>

<context:component-scan base-package="com.study.spring.d_advisor"></context:component-scan>

<!-- 打开自动代理 -->

<aop:aspectj-autoproxy/>

<!-- 被代理对象 -->

<bean id="Dog" class="com.study.dog.Dog"></bean>

<!-- 切面 -->

<bean id="MyAspectJ" class="com.study.dog.MyAspectJ"></bean>

</beans>

6.编写测试类

1 import org.junit.Test;

2 import org.junit.runner.RunWith;

3 import org.springframework.beans.factory.annotation.Autowired;

4 import org.springframework.beans.factory.annotation.Qualifier;

5 import org.springframework.test.context.ContextConfiguration;

6 import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

7

8 //完成配置文件的加载

9 @RunWith(SpringJUnit4ClassRunner.class)

10 @ContextConfiguration(locations="classpath:applicationContext.xml")

11 public class AspectJTest {

12 // 得到dog对象

13 @Autowired

14 @Qualifier("Dog")

15 private Dog dog;

16

17 @Test

18 public void Demo1() {

19 dog.eat();

20 dog.run();

21 dog.jump();

22 }

23 /*

24 * 输出结果:

25 * 饲养员叫你你猜能动

26 * 狗能吃

27 * 饲养员叫你你猜能动

28 * 狗会跑

29 * 饲养员叫你你猜能动

30 * 狗会跳

31 */

32 }

总结:上面是一个最简单的AspectJ的AOP,我们这样就可以通过输入一个”饲养员叫你你猜能动",就可以在多个方法中存在,在以后开发非常需要

那么下来来说一些非常重要的干货!

** AspectJ表达式:**

**    语法:execution(表达式)** 通过execution函数,可以定义切点的方法切入

**      execution(<访问修饰符>?<返回类型><方法名>(<参数>)<异常>)****      **

例如

execution(public * *(..)) 匹配所有类public方法

execution(* cn.study.dao..*(..)) 匹配指定包下所有类方法,不包含子包

     execution(* cn.study.dao..*(..)) ..*表示包、子孙包下所有类

     execution(* cn.study.service.UserService.*(..)) 匹配指定类所有方法

     execution(* cn.study.dao.GenericDAO+.*(..)) 匹配实现特定接口所有类方法

     execution(* save*(..)) 匹配所有save开头的方法

**   AspectJ增强**

**    **@Before 前置通知,相当于BeforeAdvice

    @AfterReturning 后置通知,相当于AfterReturningAdvice

    @Around 环绕通知,相当于MethodInterceptor

    @AfterThrowing抛出通知,相当于ThrowAdvice

    @After 最终final通知,不管是否异常,该通知都会执行

    @DeclareParents 引介通知,相当于IntroductionInterceptor (不要求掌握)

那现在我们通过上面的列子,来全面贯彻上面的干货!

对上面MyAspectJ的进行全面增强:

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声明当前类是一个切面

@Aspect

public class MyAspectJ {

//@Before代表在执行方法之前执行增强代码

@Before("execution(* com.study.dog.Dog.run(..))")

public void before(JoinPoint joinPoint){

System.out.println("前置增强...."+joinPoint);

}

//后置通知

@AfterReturning (value="execution(* com.study.dog.Dog.jump(..))",returning="returnVal")

public void afterReturin(Object returnVal){

System.out.println("后置增强....方法的返回值:"+returnVal);

}

//环绕通知

@Around(value="MyAspectJ.myPointcut()")

public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable{

System.out.println("环绕前增强....");

Object obj = proceedingJoinPoint.proceed();

System.out.println("环绕后增强....");

return obj;

}

//抛出通知

@AfterThrowing(value="MyAspectJ.myPointcut()",throwing="e")

public void afterThrowing(Throwable e){

System.out.println("不好了 出异常了!!!"+e.getMessage());

}

//最终final通知,不管是否异常,该通知都会执行

@After("MyAspectJ.myPointcut()")

public void after(){

System.out.println("最终通知...");

}

//切点的定义

@Pointcut("execution(* com.study.dog.Dog.eat(..))")

private void myPointcut(){}

}

编写测试类AspectJTest 和上面一点不变

import org.junit.Test;

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 AspectJTest {

// 得到dog对象

@Autowired

@Qualifier("Dog")

private Dog dog;

@Test

public void Demo1() {

dog.eat();

dog.run();

dog.jump();

}

}

运行结果:

通过这个例子,相信大家对于AspectJ的AOP有了一定的了解了。

最后补充一个面试题:

Advisor和Aspect的区别?

**       ** Advisor:Spring传统意义上的切面:支持一个切点和一个通知的组合.

        Aspect:可以支持多个切点和多个通知的组合.

这篇文章就讲到这里,有不足之处,欢迎大家指出,谢谢!

本文内容总结:Spring框架(5)---AspectJ实现AOP

原文链接:https://www.cnblogs.com/qdhxhz/p/6516946.html

以上是 Spring框架(5)---AspectJ实现AOP 的全部内容, 来源链接: utcz.com/z/362648.html

回到顶部