Spring系列教程——12配置文件实现AOP
配置文件其实本质上也是上一节讲的原理,只不过简化了我们的代码量而已。基本思想就是spring 创建代理对象,从spring容器中手动的获取代理对象。
上一篇:Spring系列教程——11编程实现AOP
下一篇:Spring系列教程——13AspectJ讲解
本节我们需要在前面基础上再导入一个新的jar包
链接:https://pan.baidu.com/s/1ykeaUcmOHxB5GDaOD4nb5Q
提取码:2mdp
链接:https://pan.baidu.com/s/1PiFCtYldUefZtF42Z07f4g
提取码:mjeq
一.半自动实现
在上一节当中我们实现代理需要切面类,接口,工厂类,目标类,而在配置文件半自动实现的方式中我们不需要再写工厂类,因此称之为半自动
。
首先我们把上一章节讲的切面类修改为如下内容:(需要实现MethodInterceptor接口)
package aspect;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
//注意是org.aopalliance.intercept下面的MethodInterceptor(方法拦截类)
public class MyAspect implements MethodInterceptor {
public void before(){
System.out.println("before被执行了");
}
public void after(){
System.out.println("after被执行了");
}
@Override
public Object invoke(MethodInvocation methodInvocation) throws Throwable {
/*
代码补充区
*/
return null;
}
}
在代码补充区我们写:
System.out.println("前置代码");
//方法放行
methodInvocation.proceed();
System.out.println("后置代码");
下面我们通过配置来获取UserServiceImpl的代理;
<bean id="userService" class="service.UserServiceImpl"></bean>
<bean id="aspect" class="aspect.MyAspect"></bean>
<bean id="serviceProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
<!--根据上一章,SpringAOP的实现有两种方式:jdk与cglib,而sprig默认是jdk方式,
那么根据上一章的jdk代理的讲解,这里需要目标类,切面类,接口-->
<!--目标类-->
<property name="target" ref="userService"></property>
<!--切面类-->
<!--注意这个地方比较特殊,不可用ref而是value-->
<property name="interceptorNames" value="aspect"></property>
<!--接口-->
<property name="interfaces" value="service.IUserService"></property>
</bean>
测试代码:
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
IUserService userService = (IUserService) context.getBean("serviceProxy");
userService.updateUser();
上面是默认的JDK代理,现在我们使用CGLIB只需要修改配置文件加上一句变为:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="userService" class="service.UserServiceImpl"></bean>
<bean id="aspect" class="aspect.MyAspect"></bean>
<bean id="serviceProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
<!--目标类-->
<property name="target" ref="userService"></property>
<!--切面类-->
<property name="interceptorNames" value="aspect"></property>
<!--接口-->
<property name="interfaces" value="service.IUserService"></property>
<property name="optimize" value="true"></property>
</bean>
</beans>
最后这一小节我们还需要补充一点就是
<!--接口-->
<property name="interfaces" value="service.IUserService">
这里我们只写了一个接口如果是多个接口可以这么写(下面我在写了一个,多个接口多加几个list就行了):
<property name="interfaces">
<list value-type="service.IUserService"></list>
</property>
二.全自动实现
全自动就是可以不经过代理来织入通知,而是直接织入切入点。
这里我们需要再导入一个jar包
链接:https://pan.baidu.com/s/1Wt-27ZTmTqJ2GRr-Md0peg
提取码:4z6j
配置时的基本思路就是将切入点与通知连接起来。
仅在上面的基础上修改一下xml文件如下:
<bean id="userService" class="service.UserServiceImpl"></bean>
<bean id="aspect" class="aspect.MyAspect"></bean>
<!--proxy-target-class为true表示用CGLIB代理,否则默认为JDK-->
<aop:config proxy-target-class="true">
<!--配置切入点-->
<aop:pointcut id="muPointCut" expression="execution(* service.*.*(..))"/>
<!--配置通知与切入点连接-->
<aop:advisor advice-ref="aspect" pointcut-ref="muPointCut"></aop:advisor>
</aop:config>
运行结果为
三.补充知识
AOP联盟通知类型参考spring AOP联盟通知类型文章。