前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >猿蜕变15——一文搞懂Spring AOP的正确姿势

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

作者头像
山旮旯的胖子
发布2020-07-28 17:01:44
2190
发布2020-07-28 17:01:44
举报
文章被收录于专栏:猿人工厂猿人工厂

看过之前的蜕变系列文章,相信你对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若为接口,则为接口中的所有方法及其所有实现类中的所有方法;若为类,则为该类及其子类中的所有方法。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-06-10,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 猿人工厂 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档