spring aop的两种配置方式。


sring aop的方式有两种:(1)xml文件配置方式(2)注解的方式实现,我们可以先通过一个demo认识spring aop的实现,然后再对其进行详细的解释。

一、基于注解的springAop配置。

环境准备阶段:

(1)pom.xml:

1 <dependencies>
 2         <!-- 引入Spring-AOP等相关Jar -->
 3         <dependency>
 4             <groupId>org.springframework</groupId>
 5             <artifactId>spring-core</artifactId>
 6             <version>3.0.6.RELEASE</version>
 7         </dependency>
 8         <dependency>
 9             <groupId>org.springframework</groupId>
10             <artifactId>spring-context</artifactId>
11             <version>3.0.6.RELEASE</version>
12         </dependency>
13         <dependency>
14             <groupId>org.springframework</groupId>
15             <artifactId>spring-aop</artifactId>
16             <version>3.0.6.RELEASE</version>
17         </dependency>
18         <dependency>
19             <groupId>org.springframework</groupId>
20             <artifactId>spring-orm</artifactId>
21             <version>3.0.6.RELEASE</version>
22         </dependency>
23         <dependency>
24             <groupId>org.aspectj</groupId>
25             <artifactId>aspectjrt</artifactId>
26             <version>1.6.1</version>
27         </dependency>
28         <dependency>
29             <groupId>aspectj</groupId>
30             <artifactId>aspectjweaver</artifactId>
31             <version>1.5.3</version>
32         </dependency>
33         <dependency>
34             <groupId>cglib</groupId>
35             <artifactId>cglib</artifactId>
36             <version>2.1_2</version>
37         </dependency>
38 
39         <!-- https://mvnrepository.com/artifact/com.mchange/c3p0 -->
40         <dependency>
41             <groupId>com.mchange</groupId>
42             <artifactId>c3p0</artifactId>
43             <version>0.9.5.2</version>
44         </dependency>
45         <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
46         <dependency>
47             <groupId>mysql</groupId>
48             <artifactId>mysql-connector-java</artifactId>
49             <version>5.1.37</version>
50         </dependency>
51 
52         <!-- https://mvnrepository.com/artifact/dom4j/dom4j -->
53         <dependency>
54             <groupId>dom4j</groupId>
55             <artifactId>dom4j</artifactId>
56             <version>1.6.1</version>
57         </dependency>
58         <!-- https://mvnrepository.com/artifact/commons-lang/commons-lang -->
59         <dependency>
60             <groupId>commons-lang</groupId>
61             <artifactId>commons-lang</artifactId>
62             <version>2.6</version>
63         </dependency>
64     </dependencies>

(2)定义接口:

1 package cn.spring.aop.dao;
 2 
 3 /**
 4  * @author Simple
 5  * @date 10:01 2019/8/20
 6  * @description
 7  */
 8 public interface UserService {
 9     public void save();
10 }

(3)接口实现类:

1 package cn.spring.aop.dao;
 2 
 3 import org.springframework.stereotype.Service;
 4 
 5 /**
 6  * @author Simple
 7  * @date 9:57 2019/8/20
 8  * @description
 9  */
10 @Service
11 public class UserServiceImpl implements UserService {
12 
13     @Override
14     public void save() {
15         System.out.println("保存成功.....");
16     }
17 }

(4) Aop类:

1 package cn.spring.aop;
 2 
 3 import org.aspectj.lang.ProceedingJoinPoint;
 4 import org.aspectj.lang.annotation.*;
 5 import org.springframework.stereotype.Component;
 6 
 7 /**
 8  * @author Simple
 9  * @date 10:06 2019/8/20
10  * @description
11  */
12 @Component
13 @Aspect
14 public class AopAspect {
15     /**
16      * 前置通知
17      */
18     @Before("execution(* cn.spring.aop.dao.UserService.save(..))")
19     public void before(){
20         System.out.println("前置通知....");
21     }
22 
23     /**
24      * 后置通知
25      * returnVal,切点方法执行后的返回值
26      */
27     @AfterReturning(value="execution(* cn.spring.aop.dao.UserService.save(..))",returning = "returnVal")
28     public void AfterReturning(Object returnVal){
29         System.out.println("后置通知...."+returnVal);
30     }
31 
32 
33     /**
34      * 环绕通知
35      * @param joinPoint 可用于执行切点的类
36      * @return
37      * @throws Throwable
38      */
39     @Around("execution(* cn.spring.aop.dao.UserService.save(..))")
40     public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
41         System.out.println("环绕通知前....");
42         Object obj= (Object) joinPoint.proceed();
43         System.out.println("环绕通知后....");
44         return obj;
45     }
46 
47     /**
48      * 抛出通知
49      * @param e
50      */
51     @AfterThrowing(value="execution(* cn.spring.aop.dao.UserService.save(..))",throwing = "e")
52     public void afterThrowable(Throwable e){
53         System.out.println("出现异常:msg="+e.getMessage());
54     }
55 
56     /**
57      * 无论什么情况下都会执行的方法
58      */
59     @After(value="execution(* cn.spring.aop.dao.UserService.save(..))")
60     public void after(){
61         System.out.println("最终通知....");
62     }
63 }

(5) spring.xml

1 <beans xmlns="http://www.springframework.org/schema/beans"
 2        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 3        xmlns:aop="http://www.springframework.org/schema/aop"
 4        xmlns:context="http://www.springframework.org/schema/context"
 5        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
 6         http://www.springframework.org/schema/aop
 7         http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
 8     <!-- 开启注解扫描 -->
 9       <context:component-scan base-package="cn.spring.aop"></context:component-scan>
10     <!-- 启动@aspectj的自动代理支持-->
11       <aop:aspectj-autoproxy />
12 </beans>

(6) 测试类:

1 package cn.spring.aop;
 2 
 3 import cn.spring.aop.dao.UserService;
 4 import cn.spring.aop.dao.UserServiceImpl;
 5 import org.springframework.context.ApplicationContext;
 6 import org.springframework.context.support.ClassPathXmlApplicationContext;
 7 
 8 /**
 9  * @author Simple
10  * @date 10:13 2019/8/20
11  * @description
12  */
13 public class TestDemo {
14     public static void main(String[] args) {
15         ApplicationContext ac =new ClassPathXmlApplicationContext("spring.xml");
16         UserService userService = (UserService) ac.getBean("userServiceImpl");
17         userService.save();
18     }
19 }

(7) 运行结果:

二、配置详解

(1)spring.xml中注解的作用

1.spring--aop:aspectj-autoproxy/aop:aspectj-autoproxy

这个是 开启事物注解权限,引入了三个jar包 aspectjweaver.jar aspectjrt.jar aspectj.jar aopalliance.jar。

2.Spring -- context:component-scan

在xml配置了这个标签后,spring可以自动去扫描base-pack下面或者子包下面的java文件,如果扫描到有@Component @Controller@Service等这些注解的类,则把这些类注册为bean。

(2)Aop类中的注解

在aop类中,编写了5种注解类型的通知函数:

@Before 前置通知

@AfterReturning 后置通知

@Around 环绕通知

@AfterThrowing 异常通知

@After 最终通知

@pointcut 定义切点匹配表达式

(3)切点表达式

  1. execution

由于Spring切面粒度最小是达到方法级别,而execution表达式可以用于明确指定方法返回类型,类名,方法名和参数名等与方法相关的部件,并且在Spring中,大部分需要使用AOP的业务场景也只需要达到方法级别即可,因而execution表达式的使用是最为广泛的。如下是execution表达式的语法:

execution(modifiers-pattern? ret-type-pattern declaring-type-pattern?name-pattern(param-pattern) throws-pattern?)  

 这里问号表示当前项可以有也可以没有,其中各项的语义如下:
  • modifiers-pattern方法的可见性,如public,protected;
  • ret-type-pattern:方法的返回值类型,如int,void等;
  • declaring-type-pattern:方法所在类的全路径名,如com.spring.Aspect;
  • name-pattern:方法名类型,如buisinessService();
  • param-pattern:方法的参数类型,如java.lang.String;
  • throws-pattern:方法抛出的异常类型,如java.lang.Exception;

如下是一个使用execution表达式的例子:

**execution( public * com.spring.service.BusinessObject.businessService(java.lang.String,..))**

上述切点表达式将会匹配使用public修饰,返回值为任意类型,并且是com.spring.BusinessObject类中名称为businessService的方法,方法可以有多个参数,但是第一个参数必须是java.lang.String类型的方法。

通配符的类型 ,主要有两种:

  • *通配符 ,该通配符主要用于匹配单个单词,或者是以某个词为前缀或后缀的单词。

如下示例表示返回值为任意类型,在com.spring.service.BusinessObject类中,并且参数个数为零的方法:execution(* com.spring.service.BusinessObject.*())

  • ..通配符 ,该通配符表示0个或多个项,主要用于declaring-type-pattern和param-pattern中,如果用于declaring-type-pattern中,则表示匹配当前包及其子包,如果用于param-pattern中,则表示匹配0个或多个参数。

如下示例表示匹配返回值为任意类型,并且是com.spring.service包及其子包下的任意类的名称为businessService的方法,而且该方法不能有任何参数:execution(* com.spring.service..*.businessService())

这里需要说明的是,包路径service...businessService()中的 .. 应该理解为延续前面的service路径,表示到service路径为止,或者继续延续service路径,从而包括其子包路径;后面的.businessService(),这里的*表示匹配一个单词,因为是在方法名前,因而表示匹配任意的类。

如下示例是使用..表示任意个数的参数的示例,需要注意,表示参数的时候可以在括号中事先指定某些类型的参数,而其余的参数则由..进行匹配:

execution(* com.spring.service.BusinessObject.businessService(java.lang.String,..))

三、基于xml的SpringAop配置

xml配置主要是将注解转换为xml这里我们在上述的情况下做下修改,主要修改两个地方:1,spring.xml,2 aop类

1.springaop.xml

1 <beans xmlns="http://www.springframework.org/schema/beans"
 2        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 3        xmlns:aop="http://www.springframework.org/schema/aop"
 4        xmlns:context="http://www.springframework.org/schema/context"
 5        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
 6         http://www.springframework.org/schema/aop
 7         http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
 8     <!--基于配置需要我们手动进行配置-->
 9     <!-- dao 实例 -->
10     <bean id="userService" class="cn.spring.aop.dao.UserServiceImpl"></bean>
11     <!-- 切面类 -->
12     <bean id="aop" class="cn.spring.aop.AopAspect2"></bean>
13     <!-- Aop配置 -->
14     <aop:config>
15         <!-- 定义一个切入点表达式: 拦截哪些方法 -->
16         <aop:pointcut expression="execution(* cn.spring.aop.dao.UserService.*(..))"  id="pt"/>
17         <!-- 切面 -->
18         <aop:aspect ref="aop">
19             <!-- 环绕通知 -->
20             <aop:around method="around" pointcut-ref="pt"/>
21             <!-- 前置通知: 在目标方法调用前执行 -->
22             <aop:before method="before" pointcut-ref="pt"/>
23             <!-- 后置通知: -->
24             <aop:after method="after" pointcut-ref="pt"/>
25             <!-- 返回后通知 -->
26             <aop:after-returning method="afterReturning" pointcut-ref="pt" />
27             <!-- 异常通知 -->
28             <aop:after-throwing method="after" pointcut-ref="pt"/>
29         </aop:aspect>
30     </aop:config>
31 </beans>

2.aop类 AopAspect2

1 package cn.spring.aop;
 2 
 3 import org.aspectj.lang.ProceedingJoinPoint;
 4 import org.aspectj.lang.annotation.*;
 5 import org.springframework.stereotype.Component;
 6 
 7 /**
 8  * @author Simple
 9  * @date 10:06 2019/8/20
10  * @description
11  */
12 @Component
13 @Aspect
14 public class AopAspect2 {
15     /**
16      * 前置通知
17      */
18     public void before(){
19         System.out.println("前置通知....");
20     }
21 
22     /**
23      * 后置通知
24      * returnVal,切点方法执行后的返回值
25      */
26     public void afterReturning(){
27         System.out.println("后置通知....");
28     }
29 
30 
31     /**
32      * 环绕通知
33      * @param joinPoint 可用于执行切点的类
34      * @return
35      * @throws Throwable
36      */
37     public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
38         System.out.println("环绕通知前....");
39         Object obj= (Object) joinPoint.proceed();
40         System.out.println("环绕通知后....");
41         return obj;
42     }
43 
44     /**
45      * 抛出通知
46      * @param e
47      */
48     public void afterThrowable(Throwable e){
49         System.out.println("出现异常:msg="+e.getMessage());
50     }
51 
52     /**
53      * 无论什么情况下都会执行的方法
54      */
55     public void after(){
56         System.out.println("最终通知....");
57     }
58 }

3.测试方法

1 package cn.spring.aop;
 2 
 3 import cn.spring.aop.dao.UserService;
 4 import cn.spring.aop.dao.UserServiceImpl;
 5 import org.springframework.context.ApplicationContext;
 6 import org.springframework.context.support.ClassPathXmlApplicationContext;
 7 
 8 /**
 9  * @author Simple
10  * @date 10:13 2019/8/20
11  * @description
12  */
13 public class TestDemo {
14     public static void main(String[] args) {
15         ApplicationContext ac =new ClassPathXmlApplicationContext("springaop.xml");
16         UserService userService = (UserService) ac.getBean("userService");
17         userService.save();
18     }
19 }

4.运行结果

现在在开发中主要是使用注解进行开发,方便快捷,但是更多的是配置和注解一块使用,springaop在配置方面很多都是这种注解加配置,原因主要是方便管理维护。我们这里主要讲的是两种方式的使用和切点表达式。


原文链接:https://www.cnblogs.com/hang-on/p/11383289.html