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

  • 相关阅读:
    剑指Offer-11.二进制中1的个数(C++/Java)
    剑指Offer-10.矩形覆盖(C++/Java)
    剑指Offer-9.变态跳台阶(C++/Java)
    UVA 1608 Non-boring sequence 不无聊的序列(分治,中途相遇)
    UVA1607 Gates 与非门电路 (二分)
    UVA 1451 Average平均值 (数形结合,斜率优化)
    UVA 1471 Defense Lines 防线 (LIS变形)
    UVA 1606 Amphiphilic Carbon Molecules 两亲性分子 (极角排序或叉积,扫描法)
    UVA 11134 FabledRooks 传说中的车 (问题分解)
    UVA 1152 4 Values Whose Sum is Zero 和为0的4个值 (中途相遇)
  • 原文地址:https://www.cnblogs.com/hang-on/p/11383289.html
Copyright © 2011-2022 走看看