猿蜕变15——一文搞懂Spring AOP的正确姿势

2020-07-28 17:01:44 浏览数 (1)

看过之前的蜕变系列文章,相信你对mybatis有了应用方面的认识。但是这些要完成你的蜕变还不够,考虑到大家的基础知识,我们继续回到spring的话题上来,我们一起聊一聊AOP。

Spring当然是支持AOP这种编程思想的。AspectJ也是一个AOP的编程框架,实现简洁,使用方便,并且支持注解方式,Spring在2.0版本以后AspectJ的AOP实现纳入了自己阵营,只不过在代码将织入这一个步骤,还是需要有Spring AOP的方式去完成。一般来说,使用Spring的AOP模块,在一般使用的是AspectJ的实现方式。

接下来我们就用一个xml方式的例子,来做一个AOP编程。

修改pom.xml增加依赖:

代码语言:javascript复制
<!--  使用AOP加入aspectj依赖-->
       <dependency>
                     <groupId>org.aspectj</groupId>
                     <artifactId>aspectjweaver</artifactId>
                     <version>1.7.4</version>
              </dependency>
   <!--  使用AOP加入Spring对AOP的aspectj的支持依赖-->
              <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-aspects</artifactId>
        <version>4.1.2.RELEASE</version>
    </dependency>

代码示例:

为了演示效果,给TravelRouteService增加方法:

代码语言:javascript复制
package com.pz.study.frame.spring.service;
 
import java.util.List;
 
import com.pz.study.frame.spring.domain.TravelRoute;
 
 
/**
 * 线路Service
 */
public interface TravelRouteService {
 
 
    /**
     * 根据id查询
     * @param rid
     * @return
     */
    public TravelRoute findTravelRouteById(StringtravelRouteId);
   
   
    /**
     * 需改线路
     * @param rid
     * @return
     */
    public TravelRoute updateTravelRouteById(StringtravelRouteId);
   
   
    /**
     * 删除线路
     * @param rid
     * @return
     */
    public TravelRoute deleteTravelRouteById(StringtravelRouteId);
   
    /**
     * 分页查询线路列表
     * @param startRow
     * @param endRow
     * @return
     */
    public List<TravelRoute>findTravelRouteByPage(int startRow ,int endRow);
   
    /**
     * 增加线路
     * @param travelRoute
     * @throws Exception
     */
    public void addTravelRoute(TravelRoute travelRoute) throws Exception;
}

修改实现类:

代码语言:javascript复制
package com.pz.study.frame.spring.service.impl;
 
import java.util.List;
 
import javax.annotation.Resource;
 
import org.springframework.stereotype.Service;
 
import com.pz.study.frame.spring.domain.TravelRoute;
import com.pz.study.frame.spring.manager.TravelRouteManager;
import com.pz.study.frame.spring.service.TravelRouteService;
package com.pz.study.frame.spring.service.impl;
 
import java.util.List;
 
import javax.annotation.Resource;
 
import org.springframework.stereotype.Service;
 
import com.pz.study.frame.spring.domain.TravelRoute;
import com.pz.study.frame.spring.manager.TravelRouteManager;
import com.pz.study.frame.spring.service.TravelRouteService;
 
@Service(value="TravelRouteService")
public class TravelRouteServiceImpl implements TravelRouteService {
      
       @Resource(name="travelRouteManager")
       private TravelRouteManager travelRouteManager;
      
       public TravelRouteServiceImpl(){
              System.out.println("TravelRouteServiceImpl被实例化了");
       }
 
       @Override
       public TravelRoute findTravelRouteById(StringtravelRouteId) {
              System.out.println("=====findTravelRouteById=====被执行了");
              returntravelRouteManager.findTravelRouteById(travelRouteId);
       }
      
      
      
   
      
       @Override
       public TravelRoute updateTravelRouteById(StringtravelRouteId) {
             
              System.out.println("=====updateTravelRouteById=====被执行了");
              returnnull;
                           
       }
 
       @Override
       public TravelRoute deleteTravelRouteById(StringtravelRouteId) {
              System.out.println("=====deleteTravelRouteById=====被执行了");
              returnnull;
                           
       }
 
       @Override
       public List<TravelRoute>findTravelRouteByPage(int startRow, int endRow) {
              System.out.println("=====findTravelRouteByPage=====被执行了");
              return null;
       }
      
      
 
       @Override
       public void addTravelRoute(TravelRoute travelRoute) throws Exception {
             
              System.out.println("=====addTravelRoute=====被执行了");
             
              thrownew Exception("addTravelRoute===Exception");
             
       }
 
       public void init() {
          System.out.println("我是初始方法init我被执行了");
       }
 
       public void destroy() {
          System.out.println("我是销毁方法destroy我被执行了");
       }
 
       public void setTravelRouteManager(TravelRouteManager travelRouteManager) {
              this.travelRouteManager = travelRouteManager;
       }
      
      
 
}
 

编写切面类FristAspect:

代码语言:javascript复制
package com.pz.study.frame.spring.aspect;
 
import org.aspectj.lang.ProceedingJoinPoint;
 
public class FristAspect {
 
       public void before() {
              System.out.println("===before====方法前增强========");
       }
 
       public void after() {
              System.out.println("===after=====最终增强========");
       }
 
       public void afterThrowing(Exception e) {
              System.out.println("===afterThrowing=====异常通知========:"   e);
       }
 
       public void afterReturning(int result) {
              System.out.println("===afterReturning=====返回后通知增强========"   result);
       }
 
       public Object around(ProceedingJoinPoint pjp) throws Throwable {
              System.out.println("===around=====环绕增强:前========:");
              Object proceed = pjp.proceed();
              System.out.println("===around=====环绕增强:后========:");
 
              return proceed;
       }
}

编写Spring AOP相关的配置文件spring-aop.xml,配置文件:

代码语言:javascript复制
<?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: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/aop
       http://www.springframework.org/schema/aop/spring-aop.xsd
       http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd">
 
   
    <!-- 注入Aspect实现类 -->
<bean id="fristAspect"class="com.pz.study.frame.spring.aspect.FristAspect"/>
 
  <!-- 注入Aspect实现类 -->
    <bean id="fristAspect"class="com.pz.study.frame.spring.aspect.FristAspect"/>
 
 
    <!--配置aop-->
    <aop:config>
        <!--定义切入点-->
        <aop:pointcut id="addTravelRoutePointcut" expression="execution(* com.pz.study.frame.spring.service.impl.TravelRouteServiceImpl.addTravelRoute(..))"/>
        <aop:pointcut id="updateTravelRouteByIdPointcut" expression="execution(*com.pz.study.frame.spring.service.impl.TravelRouteServiceImpl.updateTravelRouteById(..))"/>
        <aop:pointcut id="deleteTravelRouteByIdPointcut" expression="execution(*com.pz.study.frame.spring.service.impl.TravelRouteServiceImpl.deleteTravelRouteById(..))"/>
        <aop:pointcut id="findTravelRouteByIdPointcut" expression="execution(* com.pz.study.frame.spring.service.impl.TravelRouteServiceImpl.findTravelRouteById(..))"/>
        <aop:pointcut id="findTravelRouteByPagePointcut" expression="execution(* com.pz.study.frame.spring.service.impl.TravelRouteServiceImpl.findTravelRouteByPage(..))"/>
 
        <!--定义切面-->
        <aop:aspect ref="fristAspect">
            <!--前置增强-->
            <aop:before method="before" pointcut-ref="updateTravelRouteByIdPointcut"/>
            <!--后置增强-->
            <aop:after-returning method="afterReturning" pointcut-ref="deleteTravelRouteByIdPointcut" returning="result"/>
            <!--异常增强-->
            <aop:after-throwing method="afterThrowing" pointcut-ref="addTravelRoutePointcut" throwing="e"/>
            <!--最终增强-->
            <aop:after method="after"pointcut-ref="findTravelRouteByIdPointcut"/>
            <!--环绕增强-->
            <aop:around method="around" pointcut-ref="findTravelRouteByPagePointcut"/>
        </aop:aspect>
    </aop:config>

不要忘记在applicationContext.xml引入新增的配置文件噢

<importresource="spring-aop.xml"/>

编写测试用例感受下效果:

代码语言:javascript复制
@Test
       public void testAop(){
             
 
              ApplicationContext applicationContext= new ClassPathXmlApplicationContext("applicationContext.xml");
               
               TravelRouteController travelRouteController=(TravelRouteController)applicationContext.getBean("travelRouteController");
               TravelRouteServicetravelRouteService=(TravelRouteService) applicationContext.getBean("travelRouteService");
               
               travelRouteService.findTravelRouteById("testAop");
               travelRouteService.updateTravelRouteById("testAop");
               travelRouteService.deleteTravelRouteById("testAop");
               travelRouteService.findTravelRouteByPage(0,10);
               
               try {
                     travelRouteService.addTravelRoute(new TravelRoute());
              } catch (Exception e) {
                     // TODO Auto-generated catch block
                     e.printStackTrace();
              }
             
             
       }

===after=====最终增强========

===before====方法前增强========

=====updateTravelRouteById=====被执行了

=====deleteTravelRouteById=====被执行了

===around=====环绕增强:前========:

=====findTravelRouteByPage=====被执行了

===around=====环绕增强:后========:

=====addTravelRoute=====被执行了

===afterThrowing=====异常通知========:java.lang.Exception: addTravelRoute===Exception

<aop:config>标签,定义了一组AOP的配置。

<aop:ponintcut>子标签,定义切入点,id表示切入点的唯一编号,expression为切入点的值,需要满足excution表达式

<aop:aspect>自标签的ref属性,指定使用那个切面。

<aop:before>定义前置增强,method为切面bean中的方法名,指定使用切面中的方法来实现增强。

<aop:after>定义最终增强,method为切面bean中的方法名,指定使用切面中的方法来实现增强。

<aop:after-returning>定义返回后增强,method为切面bean中的方法名,指定使用切面中的方法来实现增强。

<aop:after-throwing>定义异常发生增强,method为切面bean中的方法名,指定使用切面中的方法来实现增强。

<aop:around>定义环绕增强,method为切面bean中的方法名,指定使用切面中的方法来实现增强。

AspectJ提供了excution表达式用于定义切入点,表达式语法如下:

execution (

[modifiers-pattern] 访问权限类型

ret-type-pattern 返回值类型

[declaring-type-pattern] 全限定性类名

name-pattern(param-pattern) 方法名(参数名)

[throws-pattern] 抛出异常类型

)

切入点的定义需要匹配目标的方法名,使用excution表达式时,[ ]的部分是可以省略的,各部间使用空格分隔。

下面是一些表达式的例子。

举例:

execution(public * *(..))

表单式含义:任意公共方法。

execution(* set*(..))

表单式含义:任何一个以“set”开始的方法。

execution(* com.pz.study.frame.spring.service*.*(..))

表单式含义:定义在 com.pz.study.frame.spring.service 包里的所有类和方法。

execution(* com.pz.study.frame.spring.service..*.*(..))

表单式含义:定义在 com.pz.study.frame.spring.service包或者子包里的所有类和方法。

注意:“..”出现在表达式中时,后面必须跟“*”,表示包、子包下的所有类。

execution(* *.service.*.*(..))

表单式含义:只有一级包下的 serivce 子包下所有类(接口)中所有方法为切入点

execution(* *..service.*.*(..))

表单式含义:所有包下的 serivce 子包下所有类(接口)中所有方法为切入点

execution(* *.IService.*(..))

表单式含义:一级包下的 IService接口中所有方法为切入点

execution(* *.. IService.*(..))

表单式含义:所有包下的 IService接口中所有方法为切入点

execution(*com.pz.study.frame.spring.service.TravelRouteService.*(..))

表单式含义:com.pz.study.frame.spring.service.TravelRouteService 接口中的所有方法。

execution(*com.pz.study.frame.spring.service.TravelRouteService .*(..))

表单式含义:com.pz.study.frame.spring.service.TravelRouteService若为接口,则为接口中的所有方法及其所有实现类中的所有方法;若为类,则为该类及其子类中的所有方法。

0 人点赞