Spring 的AOP(面向切面编程)
AOP是一门编程技术,spring的AOP可以这样理解:把非核心代码从核心代码块中提取出来,通过Spring达到一种即插即用的效果。通俗点来说也就是,如果执行方法1之前必须要执行一个或多个其他非该功能的一些方法,如果按传统的开发模式,则在方法1的前面写几条调用语句,这样做有有好处也有坏处,好处就是如果程序代码量少那么可以很明了的指导这些方法之间的一个关系,但如果程序比较复杂代码量很大的坏,那么该功能模块中势必会参杂很多非核心的一些代码组件在里面,使代码看起来很繁杂,通过Spring的AOP技术能对此进行改善代码,让非核心的代码通过Spring来插入到某个切面上(或者说是某个执行点上),这样核心代码就显得更简洁,非核心的代码或组件就不会参杂在里面了;
AOP的概念比较抽象,但只要记住3个核心概念就行:
a. Advice:是指向核心程序内部注入的代码;比如日志记录或者其他非核心的代码
b. PointCut:是指Advice注入的一个切面,也就是上面的所谓的核心代码快,通常是一些public的方法(Advice就是插入到PointCut代码的前面或后面);
c. Advisor:是指Advice和PointCut的组装者,它是实际的将Advice代码注入到PointCut代码的操作代码。
以下代码是一个简单的运用了AOP编程:
接口:
package theInterface;
public interface Bean {
public void theMethod();
}
实现类:
package impl;
import theInterface.Bean;
public class BeanImpl implements Bean {
public void theMethod() {
System.out.println(“执行的核心代码:”+
this.getClass().getName() + " says HELLO!");
}
}
定义一个Advice代码,该代码实现Spring的MethodBeforeAdvice接口,它有一个方法必须实现,该方法是在PointCut代码之前调用(看名字可知意):
注意:可能有人写好这个类后Eclipse提示要求Configure build path…那么很可能还少一个包:aopalliance-1.0.jar,这个包在Spring包中没有,但运行的时候又必须有,所以Eclipse会提示导包。
这个包可在我资源里面下载
package impl;
import java.lang.reflect.Method;
import org.springframework.aop.MethodBeforeAdvice;
注意下面的方法中的Method m表示需要注入其他代码的方法,也就是实际类的核心代码,可用于进行判断是否需要执行下面的注入代码,args表示方法的参数数组,target表示方法所在类对象
public class TestBeforeAdvice implements MethodBeforeAdvice{
public void before(Method m, Object[] args, Object target)
throws Throwable {
System.out.println("需要注入的代码:"
+ this.getClass().getName() + ")");
}
}
下面定义Spring的配置文件:
<?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-2.0.xsd">
<bean id="beanTarget" class="impl.BeanImpl"/>
<bean id="bean" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="proxyInterfaces">
<value>theInterface.Bean</value>
</property>
<property name="target">
<ref local="beanTarget"/>
</property>
<property name="interceptorNames">
<list>
<value>theAdvisor</value>
</list>
</property>
</bean>
<bean id="theAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
<property name="advice">
<ref local="theBeforeAdvice"/>
</property>
<property name="pattern">
<value>theInterface/.Bean/.theMethod</value>
</property>
</bean>
<bean id="theBeforeAdvice" class="impl.TestBeforeAdvice"/>
</beans>
注意:
1. 这几个<bean>的顺序无所谓,因为程序是先把配置信息全部载入,然后在根据需要进行组装
2. 上面配置了一个名为“theBeforeAdvice”的Advice,包含了正则表达式的PointCut的Advisor.
3. Advisor通过spring的RegexpMethodPointcutAdvisor类来实现,他定义了一个名为advice的标签,该标签提供Advice所需要的类;他还定义了一个名为pattern的标签,该标签是PointCut表示的方法。
4. 配置文件同时还配置了一个工厂Bean,它是通过ProxyFactoryBean来实现的;
a. proxyInterfaces定义了接口类;
b. target定义了接口的实现类;
c. interceptorNames表示值列表属性,这个列表表示不要在target上执行的Advisor。注意:必须考虑他们的执行顺序。