13.XML配置AOP详解
1导入依赖
<dependencies>
<!--导入spring的context坐标,context依赖aop-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.1.5.RELEASE</version>
</dependency>
<!-- aspectj的织入(切点表达式需要用到该jar包) -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.13</version>
</dependency>
<!--spring整合junit-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.1.5.RELEASE</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
</dependencies>
2 创建目标接口和目标实现类
public interface AccountService {
public void transfer();
}
public class AccountServiceImpl implements AccountService {
@Override
public void transfer() {
System.out.println("转账业务········");
}
}
3 创建通知类
public class MyAdvice {
public void before(){
System.out.println("前置通知类");
}
}
4.在核心配置文件中配置织入关系,及切面
<?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"
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">
<!-- 目标类交给IOC容器-->
<bean id="accountService" class="com.weihong.service.serviceImpl.AccountServiceImpl"></bean>
<!--将通知类交给IOC容器-->
<bean id="myAdvice" class="com.weihong.advice.MyAdvice"></bean>
<!-- aop配置-->
<aop:config>
<!-- 引入通知类-->
<aop:aspect ref="myAdvice">
<!-- -配置目标类的transfer方法执行时,使用通知类的before方法进行前置增强-->
<aop:before method="before" pointcut="execution(* com.weihong.service.serviceImpl.AccountServiceImpl.transfer())"></aop:before>
</aop:aspect>
</aop:config>
</beans>
5.编写测试代码
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class Mytest {
@Autowired
private AccountService accountService;
@Test
public void testTransfer(){
accountService.transfer();
}
}
6.XML配置AOP详解
切点表达式
表达式语法:
execution([修饰符] 返回值类型 包名.类名.方法名(参数))
- 访问修饰符可以省略
- 返回值类型、包名、类名、方法名可以使用星号 * 代替,代表任意
- 包名与类名之间一个点 . 代表当前包下的类,两个点 … 表示当前包及其子包下的类
- 参数列表可以使用两个点 … 表示任意个数,任意类型的参数列表
execution([修饰符] 返回值类型 包名.类名.方法名(参数))
execution(public void com.lagou.servlet.impl.AccountServiceImpl.transfer(java.lang.String))
- 访问修饰符可以省略
execution(void com.lagou.servlet.impl.AccountServiceImpl.transfer(java.lang.String))
- 返回值类型、包名、类名、方法名可以使用星号 * 代替,代表任意
execution(* *.*.*.*.*.*())
- 包名与类名之间一个点 . 代表当前包下的类,两个点 .. 表示当前包及其子包下的类
execution(* *..*.*())
- 参数列表可以使用两个点 .. 表示任意个数,任意类型的参数列表
execution(* *..*.*(..))
7.切点表达式抽取
当多个增强的切点表达式相同时,可以将切点表达式进行抽取,在增强中使用 pointcut-ref 属性代替pointcut 属性来引用抽取后的切点表达式。
<!-- 目标类交给IOC容器-->
<bean id="accountService" class="com.weihong.service.serviceImpl.AccountServiceImpl"></bean>
<!--将通知类交给IOC容器-->
<bean id="myAdvice" class="com.weihong.advice.MyAdvice"></bean>
<!-- aop配置-->
<aop:config>
<!-- 抽取的切点表达式-->
<aop:pointcut id="myPointCut" expression="execution(* com.weihong.service.serviceImpl.AccountServiceImpl.*(..))"/>
<!-- 配置切面:切入点+通知-->
<aop:aspect ref="myAdvice">
<aop:before method="before" pointcut-ref="myPointCut"/>
<aop:after-returning method="afterReturning" pointcut-ref="myPointCut"/>
<aop:after-throwing method="afterThrowing" pointcut-ref="myPointCut"/>
<aop:after method="after" pointcut-ref="myPointCut"/>
// <aop:around method="around" pointcut-ref="myPointcut"/>
</aop:aspect>
</aop:config>
8. 通知类型
通知的配置语法:
<aop:通知类型 method=“通知类中方法名” pointcut=“切点表达式"></aop:通知类型>
注意:
- 后置通知和异常通知只能有一个出现。
- 通常情况下,环绕通知都是独立使用的
通知类:配置环绕通知
// Proceeding JoinPoint : 正在执行的连接点:切点
public Object around(ProceedingJoinPoint pjp){
// 切点方法执行
Object proceed = null;
try {
System.out.println("前置通知执行了");
proceed = pjp.proceed();
System.out.println("后置通知执行了");
} catch (Throwable throwable) {
throwable.printStackTrace();
System.out.println("异常通知执行了");
}finally {
System.out.println("最终通知执行了");
}
return proceed;
}
9.知识小结
* aop织入的配置
<aop:config>
<aop:aspect ref=“通知类”>
<aop:before method=“通知方法名称” pointcut=“切点表达式"></aop:before>
</aop:aspect>
</aop:config>
* 通知的类型
前置通知、后置通知、异常通知、最终通知
环绕通知
* 切点表达式
execution([修饰符] 返回值类型 包名.类名.方法名(参数))