专栏首页猿人工厂猿蜕变15——一文搞懂Spring AOP的正确姿势

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

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

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

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

修改pom.xml增加依赖:

<!--  使用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增加方法:

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;
}

修改实现类:

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:

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,配置文件:

<?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"/>

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

@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若为接口,则为接口中的所有方法及其所有实现类中的所有方法;若为类,则为该类及其子类中的所有方法。

本文分享自微信公众号 - 猿人工厂(gh_deca5a88e287),作者:山旮旯的胖子

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2020-06-10

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 猿蜕变系列2——一文搞懂spring的花式DI

    看过之前的猿思考系列文章,相信你对java方面的基础有了一定的认识。经过之前的进化和思考的锻炼,也该是时候像模像样的做一些事情了。上一章节我们讲解了Spring...

    山旮旯的胖子
  • 猿蜕变系列1——春天的故事

    看过之前的猿思考系列文章,相信你对java方面的基础有了一定的认识。经过之前的进化和思考的锻炼,也该是时候像模像样的做一些事情了。比如框架的学习。

    山旮旯的胖子
  • 猿实战01——vue后台前端框架搭建

    猿实战是一个原创系列文章,通过实战的方式,采用前后端分离的技术结合SpringMVC Spring Mybatis,手把手教你撸一个完整的电商系统,跟着教程走下...

    山旮旯的胖子
  • 猿蜕变系列2——一文搞懂spring的花式DI

    看过之前的猿思考系列文章,相信你对java方面的基础有了一定的认识。经过之前的进化和思考的锻炼,也该是时候像模像样的做一些事情了。上一章节我们讲解了Spring...

    山旮旯的胖子
  • 单独设置UIView的坐标x或y或width或height

    版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u010105969/article/details/...

    用户1451823
  • zabbix 域名证书过期检测

    以谁为师
  • Java之数字处理类浅析

    包装类: 数据类型相对的包装类: byte---Byte short---Short int---Integer long---Long float---Flo...

    二十三年蝉
  • 【TestNG快速上手】一、接口自动化

    TestNG是基于java语言并集成JUnit和NUnit的测试框架,具有如下特性:

    软测小生
  • 工具的重要性就不需要我强调了吧?!~

    前两天自从在视频号分享了“新一代图像编辑器”后,有好多小伙伴问我网站,这次索性将链接放在了文章下方,供大家试玩。

    mixlab
  • 你的第一个渐进式网站应用(3)

    应用程序的shell是为渐进式网站应用的用户界面提供所需的最小HTML,CSS和JavaScript能力,并且是确保可靠的良好性能的组件之一。它的第一次加载会非...

    RP道貌不岸然

扫码关注云+社区

领取腾讯云代金券