3、AOP
(1)Aspect-oriented Programming
l 补充OOP
l 分解问题的各个方面(或关系)
l 模块化关系
l 用法:
? 持久化
? 事务管理
? 安全
? 日志管理
? 调试
(2)AOP概念
l Aspect:模块化关系(concern)
l Joinpoint:程序执行时的一个点
l Advice:在具体joinpoint做的动作
l Pointcut:一个Advice应该激活的指定joinpoint集合
l Introduction:添加方法或域到Advice类中
(3)Pointcut
l 一个Advice应该激活的指定joinpoint集合
public interface Pointcut {
ClassFilter getClassFilter();
MethodMatcher getMethodMatcher();
}
public interface ClassFilter {
boolean matches(Class clazz);
}
public interface MethodMatcher {
boolean matches(Method m, Class targetClass);
boolean matches(Method m, Class targetClass, Object[] args);
boolean isRuntime();
}
限制pointcut为一组target类;静态pointcuts不需要使用带参数的方法
(4)Pointcut实现
l 正则表达式
<bean id="gettersAndSettersPointcut"
class="org.springframework.aop.support.RegexpMethodPointcut">
<property name="patterns">
<list>
<value>.*\.get.*</value>
<value>.*\.set.*</value>
</list>
</property>
</bean>
方法名全路经匹配Perl5正则表达式
(5)Advice
l 在具体joinpoint做的动作
public interface MethodInterceptor extends Interceptor {
Object invoke(MethodInvocation invocation) throws Throwable;
}
Spring使用包围joinpoint的拦截器(Interceptor)链来实现Advice
l 例子:
public class DebugInterceptor implements MethodInterceptor {
public Object invoke(MethodInvocation invocation)
throws Throwable {
System.out.println(">> " + invocation); // before
Object rval = invocation.proceed();
System.out.println("<< Invocation returned"); // after
return rval;
}
}
(6)Advice类型
l Around Advice(如前面的例子)
l Before Advice
l Throws Advice
l After returning Advice
l Introduction Advice
(7)Spring Advisors
l PointcutAdvisor = Pointcut + Advice
l 每个内建的Advice都有一个Advisor
l 例子:
<bean id="gettersAndSettersAdvisor"
class="...aop.support.RegexpMethodPointcutAroundAdvisor">
<property name="interceptor">
<ref local="interceptorBean"/>
</property>
<property name="patterns">
<list>
<value>.*\.get.*</value>
<value>.*\.set.*</value>
</list>
</property>
</bean>
(8)ProxyFactory
l 使用ProxyFactory获得Advised对象
? 定义应用的pointcuts和advices
? 以代理对象返回interceptor
? 使用Java动态代理或CGLIB2(可以代理接口和类)
l 编程方式创建AOP代理
ProxyFactory factory = new ProxyFactory(myBusinessInterfaceImpl);
factory.addInterceptor(myMethodInterceptor);
factory.addAdvisor(myAdvisor);
MyBusinessInterface b = (MyBusinessInterface)factory.getProxy();
(9)ProxyFactoryBean
l 用来获得Bean的代理
l 要代理的Bean:
<bean id="personTarget" class="eg.PersonImpl">
<property name="name"><value>Tony</value></property>
<property name="age"><value>51</value></property>
</bean>
PersonImpl实现Person接口
l Interceptors和Advisors:
<bean id="myAdvisor" class="eg.MyAdvisor">
<property name="someProperty"><value>Something</value></property>
</bean>
<bean id="debugInterceptor" class="...aop.interceptor.NopInterceptor">
</bean>
l 代理:
<bean id="person" class="...aop.framework.ProxyFactoryBean">
<property name="proxyInterfaces"><value>eg.Person</value></property>
<property name="target"><ref local="personTarget"/></property>
<property name="interceptorNames">
<list>
<value>myAdvisor</value>
<value>debugInterceptor</value>
</list>
</property>
</bean>
l 使用Bean:
? 客户程序应该获得person Bean,而不是personTarget
? 可以通过应用程序context或编程方式来访问
<bean id="personUser" class="com.mycompany.PersonUser">
<property name="person"><ref local="person" /></property>
</bean>
Person person = (Person) factory.getBean("person");
l 如果是代理类而不是接口
? 将proxyTargetClass设置为true,来替代proxyInterfaces
? 代理要扩展target类(由CGLIB来构造)
<bean id="person" class="...aop.framework.ProxyFactoryBean">
<property name="proxyTargetClass"><value>true</value></property>
<property name="target"><ref local="personTarget"/></property>
<property name="interceptorNames">
<list>
<value>myAdvisor</value>
<value>debugInterceptor</value>
</list>
</property>
</bean>
(10)AutoProxy
l 自动代理的创建:
? 只要定义targets
? 选择的Bean会被自动代理
l 不需要为每个target Bean使用ProxyFactoryBean
(11)BeanNameAutoProxyCreator
l 使用Bean名选择targets
<bean id="employee1" class="eg.Employee">...</bean>
<bean id="employee2" class="eg.Employee">...</bean>
<bean id="myInterceptor" class="eg.DebugInterceptor"/>
<bean id="beanNameProxyCreator"
class="...aop.framework.autoproxy.BeanNameAutoProxyCreator">
<property name="beanNames"><value>employee*</value></property>
<property name="interceptorNames">
<list>
<value>myInterceptor</value>
</list>
</property>
</bean>
(12)AdvisorAutoProxyCreator
l 自动应用Advisors到context中的Bean
? 每个Advisor对应一个pointcut和advice
? 如果pointcut应用到Bean,就会被advice拦截
l 有助于保持同一个advice应用到多个事务对象的一致性
l 不可能获得没有advised的对象
l 例子:
<bean id="debugInterceptor" class="app.DebugInterceptor"/>
<bean id="getterDebugAdvisor"
class="...aop.support.RegexpMethodPointcutAdvisor">
<constructor-arg>
<ref bean="debugInterceptor"/>
</constructor-arg>
<property name="pattern"><value>.*\.get.*</value></property>
</bean>
这个Advisor应用debugInterceptor到任何类的所有get方法
<bean id="autoProxyCreator"
class="...aop.framework.autoproxy.AdvisorAutoProxyCreator">
<property name="proxyTargetClass"><value>true</value></property>
</bean>
(13)AOP高级特性
l 元数据驱动的自动代理
l 目标源(TargetSources)
? 热交换目标源:当允许调用者保持他的引用时,允许切换代理的Bean
? 目标源池:维护相同实例的池,在方法激活时释放对象到池中