猿蜕变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若为接口,则为接口中的所有方法及其所有实现类中的所有方法;若为类,则为该类及其子类中的所有方法。
- CSS3蒙版 — 元旦快乐!
- 轮播图效果,不再局限于JS制作!
- 【解疑答惑】css中经常被忽略的代码陷阱
- 时间序列预测全攻略(附带Python代码)
- “鼠标移入显示悬浮框”特效,也可以“高大上”
- 用交叉验证改善模型的预测表现(适用于Python和R)
- 前端特效制作 | CSS3圆形风格面包屑导航
- CSS3 倒影
- 写一只具有识别能力的图片爬虫
- 【今日问题】变量未初始化引起的崩溃
- 前端特效开发 | 点击查看大图相册效果
- 开发 | 星际争霸2人工智能研究环境 SC2LE 初体验
- 开发 | 我做了12万条的影评分析,告诉你《战狼Ⅱ》都在说些啥
- JavaScript | 函数定义的两种方法;预编译与执行
- java教程
- Java快速入门
- Java 开发环境配置
- Java基本语法
- Java 对象和类
- Java 基本数据类型
- Java 变量类型
- Java 修饰符
- Java 运算符
- Java 循环结构
- Java 分支结构
- Java Number类
- Java Character类
- Java String类
- Java StringBuffer和StringBuilder类
- Java 数组
- Java 日期时间
- Java 正则表达式
- Java 方法
- Java 流(Stream)、文件(File)和IO
- Java 异常处理
- Java 继承
- Java 重写(Override)与重载(Overload)
- Java 多态
- Java 抽象类
- Java 封装
- Java 接口
- Java 包(package)
- Java 数据结构
- Java 集合框架
- Java 泛型
- Java 序列化
- Java 网络编程
- Java 发送邮件
- Java 多线程编程
- Java Applet基础
- Java 文档注释