• (一)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在配置方面很多都是这种注解加配置,原因主要是方便管理维护。我们这里主要讲的是两种方式的使用和切点表达式。

  • 相关阅读:
    一年后重翻javascript
    针对thinkphp 5框架存储过程bug而重写的存储过程的扩展类
    移动应用端的支付宝支付php开发流程
    android studio 开发中启动android项目报错sdk版本不一致解决方案
    正则表达式(一)
    linux下memcached安装以及启动
    linux如何添加服务为系统服务快速启动或关闭
    js或者jquery直接下载网页上的图片代码
    onethink多图上传
    php+redis实现多台服务器内网存储session并读取
  • 原文地址:https://www.cnblogs.com/hang-on/p/11383289.html
Copyright © 2020-2023  润新知