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 。注意:必须考虑他们的执行顺序。