spring 自动代理分析

 

不管是使用Java的动态代理还是使用CGLIB代理,虽然功能很强大,但是对于每一个类,都要在Spring的配置文档中建立相应的代理,如果只是一个很小的应用系统,还看不出来工作量有多大,但对于一个大型的企业应用来说,工作量就太大了,而且重复性的工作很多,幸好Spring提供了一种自动代理的方式,可以减轻这部分工作。要使用Spring中的动态代理,org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator包是必需的。下面就讲解一下怎么来实现自动代理。

这个例子是所有类中以do开头的方法,在被调用时,都要进行日志输出。实现思路是:首先在接口TimeBookInterface中增加一个方法doCheck(),在其实现类TimeBook中实现这个方法,接着使用前面示例中的Before、After通知,然后修改配置文档,定义自动代理,最后编写测试程序,查看输出结果。具体步骤如下所示:

(1)在com.gc.impl包的接口TimeBookInterface中增加一个方法doCheck()。Time-

BookInterface.java的示例代码如下:

//******* TimeBookInterface.java**************

package com.gc.impl;

import org.apache.log4j.Level;

public interface TimeBookInterface {

         public void doAuditing(String name);

public void doCheck(String name);

}

(2)在com.gc.action包的类TimeBook中增加一个方法doCheck(),doCheck()方法中编写财务关账的代码。TimeBook.java的示例代码如下:

//******* TimeBook.java**************

package com.gc.action;

import com.gc.impl.TimeBookInterface;

public class TimeBook implements TimeBookInterface {

public void doAuditing(String name) {

//审核数据的相关程序

System.out.println ("审核数据的相关程序正在执行...");

}

public void doCheck(String name) {                 

                   //关账的相关程序

System.out.println ("财务关账的相关程序正在执行...");  

         }

}

(3)使用前面示例中负责输出日志信息的类LogBefore,该类实现了接口Method-

BeforeAdvice,重写了before()方法。LogBefore.java的示例代码如下:

//******* LogBefore.java**************

package com.gc.action;

import java.lang.reflect.Method;

import org.apache.log4j.Level;

import org.apache.log4j.Logger;

import org.springframework.aop.MethodBeforeAdvice;

public class LogBefore implements MethodBeforeAdvice {

         private Logger logger = Logger.getLogger(this.getClass().getName());

    //用于在执行审核程序前调用该方法

    public void before(Method method, Object[] args, Object target) throws Throwable {

                   logger.log(Level.INFO, args[0] + " 开始审核数据...");

   }

}

(4)使用前面示例中负责输出日志信息的类LogAfter,该类实现了接口AfterReturning-

Advice,重写了afterReturning()方法。LogAfter.java的示例代码如下:

//******* LogAfter.java**************

package com.gc.action;

import java.lang.reflect.Method;

import org.apache.log4j.Level;

import org.apache.log4j.Logger;

import org.springframework.aop.AfterReturningAdvice ;

public class LogAfter implements AfterReturningAdvice {

         private Logger logger = Logger.getLogger(this.getClass().getName());

    //用于在执行审核程序后调用该方法

    public void afterReturning(Object object, Method method, Object[ ] args, Object target) throws Throwable {

                   logger.log(Level.INFO, args[0] + " 审核数据完成...");

   }

}

(5)修改配置文档config.xml,增加一个负责自动代理的Bean。config.xml的示例代码如下:

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"

"http://www.springframework.org/dtd/spring-beans.dtd">

<beans>

<bean id="HelloWorld" class="com.gc.action.HelloWorld" depends-on="date">

      <property name="msg">

          <value>HelloWorld</value>

      </property>

<property name="date">

<ref bean="date"/>

</property>

</bean>

<bean id="date" class="java.util.Date"/>

<!--以下是使用Spring AOP实现日志输出的Bean-->

<bean id="log" class="com.gc.action.LogAop"/>

<bean id="timeBook" class="com.gc.action.TimeBook"/>

<bean id="autoProxyCreator" class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"/>

<!--以下是实现Before通知-->

<bean id="logBefore" class="com.gc.action.LogBefore"/>

<bean id="logBeforeAdvisor"class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">

        <property name="advice">

            <ref bean="logBefore"/>

         </property>

              <!--指定以do开头的方法-->

        <property name="patterns">

            <value>.*do.* </value>

        </property>

    </bean>

<!--以下是实现After通知-->

<bean id="logAfter" class="com.gc.action.LogAfter"/>

<bean id="logAfterAdvisor"class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">

        <property name="advice">

            <ref bean="logAfter"/>

        </property>

               <!--指定以do开头的方法-->

        <property name="patterns">

            <value>.*do.* </value>

        </property>

    </bean>

</beans>

(6)修改测试代码TestHelloWorld,调用doCheck()方法。TestHelloWorld.java的示例代码如下:

//******* TestHelloWorld.java**************

package com.gc.test;

import com.gc.action.TimeBook;

import com.gc.action.TimeBookProxy;

import com.gc.impl.TimeBookInterface;

public class TestHelloWorld {

         public static void main(String[] args) {

             //通过ApplicationContext获取配置文档

ApplicationContext actx=new FileSystemXmlApplicationContext("config.xml");

TimeBookInterface timeBookProxy = (TimeBookInterface)actx.getBean("timeBook");

timeBookProxy.doCheck("张三");

    }

}

(7)运行测试程序,可以看到调用doCheck()方法和LogBefore、LogAfter通知的日志信息输出,如图5.12所示。

图5.12 调用doCheck()方法和LogBefore、LogAfter通知的日志信息输出

(8)修改测试代码TestHelloWorld,调用doAuditing()方法。TestHelloWorld.java的示例代码如下:

//******* TestHelloWorld.java**************

package com.gc.test;

import com.gc.action.TimeBook;

import com.gc.action.TimeBookProxy;

import com.gc.impl.TimeBookInterface;

public class TestHelloWorld {

         public static void main(String[ ] args) {

             //通过ApplicationContext获取配置文档

ApplicationContext actx=new FileSystemXmlApplicationContext("config.xml");

TimeBookInterface timeBookProxy = (TimeBookInterface)actx.getBean("timeBook");

timeBookProxy.doAuditing("张三");

    }

}

(9)运行测试程序,可以看到调用doAuditing()方法和LogBefore、LogAfter通知的日志信息输出,如图5.13所示。

图5.13 调用doAuditing()方法和LogBefore、LogAfter通知的日志信息输出

(10)修改配置文档config.xml,把LogBefore通知定义为指定doCheck()方法,把LogAfter通知定义为指定doAuditing()方法。config.xml的示例代码如下:

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"

"http://www.springframework.org/dtd/spring-beans.dtd">

<beans>

<bean id="HelloWorld" class="com.gc.action.HelloWorld" depends-on="date">

      <property name="msg">

          <value>HelloWorld</value>

      </property>

<property name="date">

<ref bean="date"/>

</property>

</bean>

<bean id="date" class="java.util.Date"/>

<!--以下是使用Spring AOP实现日志输出的Bean-->

<bean id="log" class="com.gc.action.LogAop"/>

<bean id="timeBook" class="com.gc.action.TimeBook"/>

<bean id="autoProxyCreator" class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"/>

<!--以下是实现Before通知-->

<bean id="logBefore" class="com.gc.action.LogBefore"/>

<bean id="logBeforeAdvisor"class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">

        <property name="advice">

            <ref bean="logBefore"/>

        </property>

<!--指定对doCheck 方法有效-->

        <property name="patterns">

            <value>.*doCheck.* </value>

        </property>

    </bean>

<!--以下是实现After通知-->

<bean id="logAfter" class="com.gc.action.LogAfter"/>

<bean id="logAfterAdvisor"class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">

        <property name="advice">

            <ref bean="logAfter"/>

        </property>

<!--指定对doAuditing方法有效-->

        <property name="patterns">

            <value>.*doAuditing.* </value>

        </property>

    </bean>

</beans>

(11)修改测试代码TestHelloWorld,调用doCheck()方法。TestHelloWorld.java的示例代码如下:

//******* TestHelloWorld.java**************

package com.gc.test;

import com.gc.action.TimeBook;

import com.gc.action.TimeBookProxy;

import com.gc.impl.TimeBookInterface;

public class TestHelloWorld {

         public static void main(String[ ] args) {

             //通过ApplicationContext获取配置文档

ApplicationContext actx=new FileSystemXmlApplicationContext("config.xml");

TimeBookInterface timeBookProxy = (TimeBookInterface)actx.getBean("timeBook");

timeBookProxy.doCheck("张三");

    }

}

(12)运行测试程序,可以看到调用doCheck()方法和LogBefore通知的日志信息输出,如图5.14所示。

图5.14 调用doCheck()方法和LogBefore通知的日志信息输出

(13)修改测试代码TestHelloWorld,调用doAuditing()方法。TestHelloWorld.java的示例代码如下:

//******* TestHelloWorld.java**************

package com.gc.test;

import com.gc.action.TimeBook;

import com.gc.action.TimeBookProxy;

import com.gc.impl.TimeBookInterface;

public class TestHelloWorld {

         public static void main(String[ ] args) {

             //通过ApplicationContext获取配置文档

ApplicationContext actx=new FileSystemXmlApplicationContext("config.xml");

TimeBookInterface timeBookProxy = (TimeBookInterface)actx.getBean("timeBook");

   timeBookProxy.doAuditing("张三");

    }

}

(14)运行测试程序,可以看到调用doAuditing()方法和LogAfter通知的日志信息输出,如图5.15所示。

图5.15 调用doAuditing()方法和LogAfter通知的日志信息输出

上面的示例展示了Spring的自动代理,并接着展示了利用正则表达式进行方法的匹配,由此可以看出使用自动代理的简便。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值