Spring API级别对AOP的支持

来源:互联网 发布:c语言设计简易计算器 编辑:程序博客网 时间:2024/06/11 20:42
在Spring 2.0之前,Spring通过定义一套接口和通过ProxyFactoryBean来生产bean实例提供对AOP的支持,在2.0后,Spring推荐通过AspectJ兼容的方式来实现AOP.见http://blog.csdn.net/kkdelta/archive/2010/04/22/5515882.aspx
1,定义'方面'拦截器,最常用的接口有:
MethodInterceptor: 在方法执行的前后执行,相当于2.0的@Around.
MethodBeforeAdvice:在方法执行前执行,相当于2.0的@Before.
ThrowsAdvice :在方法异常后执行,相当于2.0的@AfterThrowing.
AfterReturningAdvice :在方法执行后执行,相当于2.0的@AfterReturning.
2,配置ProxyFactoryBean,使用ProxyFactoryBean创建AOP代理.最常用的配置项:
proxyInterfaces : 需要代理的接口名的字符串数组。如果没有提供,将为目标类使用一个CGLIB代理.
interceptorNames:Advisor的字符串数组,可以包括拦截器或其它advice的名字。顺序是很重要的,排在前面的将被优先服务。就是说列表里的第一个拦截器将能够第一个拦截调用。(Advisor是一个advice,在某些特定规则的方法执行的时候被触发)
target : 指定你希望代理的目标对象.
例子:
1,POJO bean类:
public interface IHelloWorld {    public String getContent(String helloworld);    public String testExp(String exp);}public interface IHelloWorld2 {    public String testExp2(String exp);}public class HelloWorld implements IHelloWorld,IHelloWorld2 {    protected static final Log log = LogFactory.getLog(HelloWorld.class);    public String getContent(String helloworld) {        log.info(helloworld);        return helloworld;    }      public String testExp(String exp){        log.info(exp);        return exp;    }      public String testExp2(String exp){        log.info("testExp2 " + exp);        return exp;    }}
advice 类:
public class LoggingBeforeAdvice implements  MethodBeforeAdvice {    protected static final Log log = LogFactory.getLog(LoggingBeforeAdvice.class);    public void before(Method m, Object[] args, Object target) throws Throwable {        log.info("before: The Invocation The Invocation of " + m.getName());    }}public class LoggingAfterAdvice implements AfterReturningAdvice {    protected static final Log log = LogFactory.getLog(LoggingAfterAdvice.class);    public void afterReturning(Object object, Method m, Object[] args,        Object target) throws Throwable {        log.info("after: The Invocation of " + m.getName());        }}public class DebugInterceptor implements MethodInterceptor {    public Object invoke(MethodInvocation invocation) throws Throwable {        System.out.println("Before: invocation=[" + invocation + "]");        Object rval = invocation.proceed();        System.out.println("Invocation returned");        return rval;    }}
配置文件:
<beans>    <bean id="helloworldbean" class="org.springframework.aop.framework.ProxyFactoryBean">        <property name="proxyInterfaces">            <list>                <value>com.test.spring.aop.api.IHelloWorld</value>                <value>com.test.spring.aop.api.IHelloWorld2</value>            </list>        </property>        <property name="target">            <ref local="helloworldbeanTarget" />        </property>        <property name="interceptorNames">            <list>                <value>loggingBeforeAdvice</value>                <value>debugInterceptor</value>            </list>        </property>    </bean>    <bean id="helloworldbeanTarget" class="com.test.spring.aop.api.HelloWorld" />    <bean id="loggingAfterAdvisor"        class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">        <property name="advice">                <ref local="loggingAfterAdvice" />        </property>        <property name="pattern">            <value>.*</value>        </property>    </bean>    <bean id="loggingBeforeAdvice" class="com.test.spring.aop.api.LoggingBeforeAdvice" />    <bean id="loggingAfterAdvice" class="com.test.spring.aop.api.LoggingAfterAdvice" />    <bean id="debugInterceptor" class="com.test.spring.aop.api.DebugInterceptor" /></beans>
调用代码:
       ApplicationContext context = new ClassPathXmlApplicationContext("conf/aopapiAppcontext1.xml");        IHelloWorld bean = (IHelloWorld) context.getBean("helloworldbean");        try {            bean.getContent("helloworld");                     bean.testExp("test RegexpMethodPointcutAdvisor");                      IHelloWorld2 bean2 = (IHelloWorld2)bean;                   bean2.testExp2("2 test RegexpMethodPointcutAdvisor");                 } catch (Exception e) {        }
一种较好的方法是对某一类bean设置相同的切面设置,如下:
    <bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">      <property name="beanNames"><value>hello*</value></property>      <property name="proxyTargetClass" value="true"/>      <property name="interceptorNames">        <list>          <value>debugInterceptor</value>        </list>      </property>    </bean>    <bean id="helloworldbeanTarget" class="com.test.spring.aop.api.HelloWorld" />    <bean id="debugInterceptor" class="com.test.spring.aop.api.DebugInterceptor" />
还可以定义一个模板bean,其他bean"继承"这个bean的定义,如事务管理
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"/><bean id="txProxyTemplate" abstract="true"        class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">  <property name="transactionManager" ref="transactionManager"/>  <property name="transactionAttributes">    <props>      <prop key="*">PROPAGATION_REQUIRED</prop>    </props>  </property></bean><bean id="myService1" parent="txProxyTemplate">  <property name="target">    <bean class="org.springframework.samples.MyServiceImpl1">    </bean>  </property></bean><bean id="myService2" parent="txProxyTemplate">  <property name="target">    <bean class="org.springframework.samples.MyServiceImpl2">    </bean>  </property></bean>
对于2.0以后配置事务管理则更为简单了
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"/>    <aop:config>        <aop:pointcut id="yyyProcessMethods" expression="execution(* com.xxx.yyy.*.*Processor.*(..))" />        <aop:pointcut id="yyyProcessMethods" expression="execution(* com.xxx.yyy.srv.*service.*(..))" />        <aop:advisor advice-ref="txAdvice" pointcut-ref="yyyProcessMethods" />    </aop:config>    <tx:advice id="txAdvice">        <tx:attributes><tx:method name="*" propagation="REQUIRED" /></tx:attributes>    </tx:advice>