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