分享

SpringFramework(4)

 web.anywhere 2006-03-16

3AOP

1Aspect-oriented Programming

l         补充OOP

l         分解问题的各个方面(或关系)

l         模块化关系

l         用法:

         持久化

         事务管理

         安全

         日志管理

         调试

2AOP概念

l         Aspect:模块化关系(concern

l         Joinpoint:程序执行时的一个点

l         Advice:在具体joinpoint做的动作

l         Pointcut:一个Advice应该激活的指定joinpoint集合

l         Introduction:添加方法或域到Advice类中

3Pointcut

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不需要使用带参数的方法

4Pointcut实现

l         正则表达式

<bean id="gettersAndSettersPointcut"
class="org.springframework.aop.support.RegexpMethodPointcut">
<property name="patterns">
<list>
<value>.*\.get.*</value>
<value>.*\.set.*</value>
</list>
</property>
</bean>

方法名全路经匹配Perl5正则表达式

5Advice

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;
}
}

6Advice类型

l         Around Advice(如前面的例子)

l         Before Advice

l         Throws Advice

l         After returning Advice

l         Introduction Advice

7Spring 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>

8ProxyFactory

l         使用ProxyFactory获得Advised对象

         定义应用的pointcutsadvices

         以代理对象返回interceptor

         使用Java动态代理或CGLIB2(可以代理接口和类)

l         编程方式创建AOP代理

ProxyFactory factory = new ProxyFactory(myBusinessInterfaceImpl);
factory.addInterceptor(myMethodInterceptor);
factory.addAdvisor(myAdvisor);
MyBusinessInterface b = (MyBusinessInterface)factory.getProxy();

9ProxyFactoryBean

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         InterceptorsAdvisors

<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>

10AutoProxy

l         自动代理的创建:

         只要定义targets

         选择的Bean会被自动代理

l         不需要为每个target Bean使用ProxyFactoryBean

11BeanNameAutoProxyCreator

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>

12AdvisorAutoProxyCreator

l         自动应用Advisorscontext中的Bean

         每个Advisor对应一个pointcutadvice

         如果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>

13AOP高级特性

l         元数据驱动的自动代理

l         目标源(TargetSources

         热交换目标源:当允许调用者保持他的引用时,允许切换代理的Bean

         目标源池:维护相同实例的池,在方法激活时释放对象到池中

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多