﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>语源科技BlogJava-wigalos</title><link>http://www.blogjava.net/wigalos/</link><description /><language>zh-cn</language><lastBuildDate>Sun, 12 Apr 2026 16:59:38 GMT</lastBuildDate><pubDate>Sun, 12 Apr 2026 16:59:38 GMT</pubDate><ttl>60</ttl><item><title>Spring AOP介绍</title><link>http://www.blogjava.net/wigalos/archive/2007/11/16/161006.html</link><dc:creator>wigalos</dc:creator><author>wigalos</author><pubDate>Fri, 16 Nov 2007 06:06:00 GMT</pubDate><guid>http://www.blogjava.net/wigalos/archive/2007/11/16/161006.html</guid><wfw:comment>http://www.blogjava.net/wigalos/comments/161006.html</wfw:comment><comments>http://www.blogjava.net/wigalos/archive/2007/11/16/161006.html#Feedback</comments><slash:comments>14</slash:comments><wfw:commentRss>http://www.blogjava.net/wigalos/comments/commentRss/161006.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/wigalos/services/trackbacks/161006.html</trackback:ping><description><![CDATA[<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 最近在学习spring，做了一些关于Spring AOP的总结和例子，参考书籍是李刚老师著的《轻量级J2EE企业应用实战》。如下：</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Spring AOP介绍</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Spring的AOP是上面代理模式的深入。使用Spring AOP，开发者无需实现业务逻辑对象工厂，无需实现代理工厂，这两个工厂都由Spring容器充当。Spring AOP不仅允许使用XML文件配置目标方法，ProxyHandler也允许使用依赖注入管理，Spring AOP提供了更多灵活的选择。<br />
在下面Spring AOP的示例中，InvocationHandler采用动态配置，需要增加的方法也采用动态配置，一个目标对象可以有多个拦截器（类似于代理模式中的代理处理器）。<br />
下面是原始的目标对象：<br />
//目标对象的接口<br />
public interface&nbsp; Person<br />
{<br />
&nbsp;//该接口声明了两个方法<br />
&nbsp;void info();<br />
&nbsp;void run();<br />
}<br />
下面是原始目标对象的实现类，实现类的代码如下：<br />
//目标对象的实现类，实现类实现Person接口<br />
public class PersonImpl implements Person<br />
{<br />
&nbsp;//两个成员属性<br />
&nbsp;private String name;<br />
&nbsp;private int age;<br />
&nbsp;//name属性的 setter方法<br />
&nbsp;public void setName(String name)<br />
&nbsp;{<br />
&nbsp;&nbsp;this.name = name;<br />
&nbsp;}<br />
&nbsp;//age属性的setter方法<br />
public void setAge(int age)<br />
&nbsp;{<br />
&nbsp;&nbsp;this.age = age;<br />
&nbsp;}<br />
&nbsp;//info方法，该方法仅仅在控制台打印一行字符串<br />
&nbsp;public void info()<br />
&nbsp;{<br />
&nbsp;&nbsp;System.out.println("我的名字是:&nbsp; " + name + " , 今年年龄为:&nbsp; " + age);<br />
&nbsp;}<br />
&nbsp;//run方法，该方法也在控制台打印一行字符串。<br />
&nbsp;public void run()<br />
&nbsp;{<br />
&nbsp;&nbsp;if (age &lt; 45)<br />
&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;System.out.println("我还年轻，奔跑迅速...");<br />
&nbsp;&nbsp;}<br />
&nbsp;&nbsp;else<br />
&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;System.out.println("我年老体弱，只能慢跑...");<br />
&nbsp;&nbsp;}<br />
&nbsp;}<br />
}<br />
该Person实例将由Spring容器负责产生和管理，name属性和age属性也采用依赖注入管理。<br />
为了充分展示Spring AOP的功能，此处为Person对象创建三个拦截器。第一个拦截器是调用方法前的拦截器，代码如下：<br />
//调用目标方法前的拦截器，拦截器实现MethodBeforeAdvice接口<br />
public class MyBeforeAdvice implements MethodBeforeAdvice<br />
{<br />
&nbsp;//实现MethodBeforeAdvice接口，必须实现before方法，该方法将在目标<br />
&nbsp;//方法调用之前，自动被调用。<br />
&nbsp;&nbsp;&nbsp; &nbsp;public void before(Method m, Object[] args, Object target) throws Throwable<br />
&nbsp;{<br />
&nbsp;&nbsp;System.out.println("方法调用之前...");<br />
&nbsp;&nbsp;System.out.println("下面是方法调用的信息：");<br />
&nbsp;&nbsp;System.out.println("所执行的方法是:" + m);<br />
&nbsp;&nbsp;System.out.println("调用方法的参数是：" + args);<br />
&nbsp;&nbsp;System.out.println("目标对象是：" + target);<br />
&nbsp;&nbsp;&nbsp; &nbsp;}<br />
}<br />
第二个拦截器是方法调用后的拦截器，该拦截器将在方法调用结束后自动被调用，拦截器代码如下：<br />
//调用目标方法后的拦截器，该拦截器实现AfterReturningAdvice接口<br />
public class MyAfterAdvice implements AfterReturningAdvice<br />
{<br />
&nbsp;//实现AfterReturningAdvice接口必须实现afterReturning方法，该方法将在目标方法<br />
&nbsp;//调用结束后，自动被调用。<br />
&nbsp;&nbsp;&nbsp; &nbsp;public void afterReturning(Object returnValue, Method m, Object[] args, Object target)throws Throwable<br />
&nbsp;{<br />
&nbsp;&nbsp;System.out.println("方法调用结束...");<br />
System.out.println("目标方法的返回值是 : " + returnValue);<br />
&nbsp;&nbsp;System.out.println("目标方法是 : " + m);<br />
&nbsp;&nbsp;System.out.println("目标方法的参数是 : " + args);<br />
&nbsp;&nbsp;System.out.println("目标对象是 : " + target);<br />
&nbsp;&nbsp;&nbsp; }<br />
}<br />
第三个拦截器是是Around拦截器，该拦截器既可以在目标方法之前调用，也可以在目标方法调用之后被调用。下面是Around拦截器的代码：<br />
//Around拦截器实现MethodInterceptor接口<br />
public class MyAroundInterceptor implements MethodInterceptor<br />
{<br />
&nbsp;//实现MethodInterceptor接口必须实现invoke方法<br />
&nbsp;&nbsp;&nbsp; &nbsp;public Object invoke(MethodInvocation invocation) throws Throwable<br />
&nbsp;{<br />
&nbsp;&nbsp;//调用目标方法之前执行的动作<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;System.out.println("调用方法之前: invocation对象：[" + invocation + "]");<br />
&nbsp;&nbsp;//调用目标方法<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;Object rval = invocation.proceed();<br />
&nbsp;&nbsp;//调用目标方法之后执行的动作<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;System.out.println("调用结束...");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;return rval;<br />
&nbsp;&nbsp;&nbsp; }<br />
}<br />
利用Spring AOP框架，实现之前的代理模式相当简单。只需要实现对应的拦截器即可，无需创建自己的代理工厂，只需采用Spring容器作为代理工厂。下面在Spring配置文件中配置目标bean，以及拦截器。<br />
下面是Spring配置文件的代码：<br />
&lt;?xml version="1.0" encoding="gb2312"?&gt;<br />
&lt;!--&nbsp; Spring配置文件的文件头--&gt;<br />
&lt;!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"<br />
&nbsp;"http://www.springframework.org/dtd/spring-beans.dtd"&gt;<br />
&lt;!--&nbsp; Spring配置文件的根元素--&gt;<br />
&lt;beans&gt;<br />
&nbsp;&lt;!--&nbsp; 配置目标对象--&gt;<br />
&nbsp;&lt;bean id="personTarget" class="lee.PersonImpl"&gt;<br />
&nbsp;&nbsp;&lt;!--&nbsp; 为目标对象注入name属性值--&gt;<br />
&nbsp;&nbsp;&lt;property name="name"&gt;<br />
&nbsp;&nbsp;&nbsp;&lt;value&gt;Wawa&lt;/value&gt;<br />
&nbsp;&nbsp;&lt;/property&gt;<br />
&nbsp;&nbsp;&lt;!--&nbsp; 为目标对象注入age属性值--&gt;<br />
&nbsp;&nbsp;&lt;property name="age"&gt;<br />
&nbsp;&nbsp;&nbsp;&lt;value&gt;51&lt;/value&gt;<br />
&nbsp;&nbsp;&lt;/property&gt;<br />
&nbsp;&lt;/bean&gt;<br />
&nbsp;&lt;!--&nbsp; 第一个拦截器--&gt;<br />
&nbsp;&lt;bean id="myAdvice" class="lee.MyBeforeAdvice"/&gt;<br />
&nbsp;&lt;!--&nbsp; 第二个拦截器--&gt;<br />
&nbsp;&lt;bean id="myAroundInterceptor" class="lee.MyAroundInterceptor"/&gt;<br />
&lt;!--&nbsp; 将拦截器包装成Advisor，该对象还确定代理对怎样的方法增加处理--&gt;<br />
&nbsp;&lt;bean id="runAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor"&gt;<br />
&nbsp;&nbsp;&lt;!--&nbsp; advice属性确定处理bean--&gt;<br />
&nbsp;&nbsp;&lt;property name="advice"&gt;<br />
&nbsp;&nbsp;&nbsp;&lt;!-- 此处的处理bean定义采用嵌套bean,也可引用容器的另一个bean--&gt;<br />
&nbsp;&nbsp;&nbsp;&lt;bean class="lee.MyAfterAdvice"/&gt;<br />
&nbsp;&nbsp;&lt;/property&gt;<br />
&nbsp;&nbsp;&lt;!--&nbsp; patterns确定正则表达式模式--&gt;<br />
&nbsp;&nbsp;&lt;property name="patterns"&gt;<br />
&nbsp;&nbsp;&nbsp;&lt;list&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;!--&nbsp; 确定正则表达式列表--&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;value&gt;.*run.*&lt;/value&gt;<br />
&nbsp;&nbsp;&nbsp;&lt;/list&gt;<br />
&nbsp;&nbsp;&lt;/property&gt;<br />
&nbsp;&lt;/bean&gt;<br />
&nbsp;&lt;!--&nbsp; 使用ProxyFactoryBean 产生代理对象--&gt;<br />
&nbsp;&lt;bean id="person" class="org.springframework.aop.framework.ProxyFactoryBean"&gt;<br />
&nbsp;&nbsp;&lt;!--&nbsp; 代理对象所实现的接口--&gt;<br />
&nbsp;&nbsp;&lt;property name="proxyInterfaces"&gt;<br />
&nbsp;&nbsp;&nbsp;&lt;value&gt;lee.Person&lt;/value&gt;<br />
&nbsp;&nbsp;&lt;/property&gt;<br />
&nbsp;&nbsp;&lt;!--&nbsp; 设置目标对象--&gt;<br />
&nbsp;&nbsp;&lt;property name="target"&gt;<br />
&nbsp;&nbsp;&nbsp;&lt;ref local="personTarget"/&gt;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&lt;/property&gt;<br />
&nbsp;&nbsp;&lt;!--&nbsp; 代理对象所使用的拦截器--&gt;<br />
&nbsp;&nbsp;&lt;property name="interceptorNames"&gt;<br />
&nbsp;&nbsp;&nbsp;&lt;list&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;value&gt;runAdvisor&lt;/value&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;value&gt;myAdvice&lt;/value&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;value&gt;myAroundInterceptor&lt;/value&gt;<br />
&nbsp;&nbsp;&nbsp;&lt;/list&gt;<br />
&nbsp;&nbsp;&lt;/property&gt;<br />
&nbsp;&lt;/bean&gt;<br />
&lt;/beans&gt;<br />
该配置文件使用ProxyFactoryBean来生成代理对象，配置ProxyFactoryBean工厂bean时，指定了target属性，该属性值就是目标对象，该属性值为personTarget，指定代理的目标对象为personTarget。通过interceptorNames属性确定代理需要的拦截器，拦截器可以是普通的Advice，普通Advice将对目标对象的所有方法起作用，拦截器也可以是Advisor，Advisor是Advice和切面的组合，用于确定目标对象的哪些方法需要增加处理，以及怎样的处理。在上面的配置文件中，使用了三个拦截器，其中myAdvice、myAroundInterceptor都是普通Advice，它们将对目标对象的所有方法起作用。而runAdvisor则使用了正则表达式切面，匹配run方法，即该拦截器只对目标对象的run方法起作用。<br />
<br />
下面是测试代理的主程序：<br />
public class BeanTest<br />
{<br />
&nbsp;&nbsp; &nbsp;public static void main(String[] args)throws Exception<br />
{<br />
&nbsp;&nbsp;//创建Spring容器<br />
ApplicationContext ctx = new FileSystemXmlApplicationContext("bean.xml");<br />
&nbsp;&nbsp;//获取代理对象<br />
&nbsp;&nbsp;Person p = (Person)ctx.getBean("person");<br />
&nbsp;&nbsp;//执行info方法<br />
&nbsp;&nbsp;p.info();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;System.out.println("===========================================");<br />
&nbsp;&nbsp;//执行run方法<br />
&nbsp;&nbsp;p.run();<br />
&nbsp;&nbsp;&nbsp; }<br />
}<br />
下面是程序的执行结果：<br />
方法调用之前...<br />
下面是方法调用的信息：<br />
所执行的方法是:public abstract void lee.Person.info()<br />
调用方法的参数是：null<br />
目标对象是：lee.PersonImpl@b23210<br />
调用方法之前: invocation对象：[invocation: method 'info', arguments<br />
[]; target is of class [lee.PersonImpl]]<br />
我的名字是:&nbsp; Wawa , 今年年龄为:&nbsp; 51<br />
调用结束...<br />
===========================================<br />
方法调用之前...<br />
下面是方法调用的信息：<br />
所执行的方法是:public abstract void lee.Person.run()<br />
调用方法的参数是：null<br />
目标对象是：lee.PersonImpl@b23210<br />
调用方法之前: invocation对象：[invocation: method 'run', arguments [<br />
]; target is of class [lee.PersonImpl]]<br />
我年老体弱，只能慢跑...<br />
调用结束...<br />
方法调用结束...<br />
目标方法的返回值是 : null<br />
目标方法是 : public abstract void lee.Person.run()<br />
目标方法的参数是 : null<br />
目标对象是 : lee.PersonImpl@b23210<br />
程序的执行结果中一行&#8220;=&#8221;用于区分两次调用的方法。在调用info方法时，只有myAdvice和myAroundInterceptor两个拦截器起作用，调用run方法时候，三个拦截器都起作用了。<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 通过上面的介绍，可看出Spring的AOP框架是对代理模式简化，并拓展了代理模式的使用。<br />
Spring AOP是Spring声明式事务的基础。了解Spring AOP对深入理解Spring的声明式事务管理是非常有好处的。Spring AOP还可以完成很多功能，例如基于AOP的权限检查。</p>
<p>&nbsp;</p>
 <img src ="http://www.blogjava.net/wigalos/aggbug/161006.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/wigalos/" target="_blank">wigalos</a> 2007-11-16 14:06 <a href="http://www.blogjava.net/wigalos/archive/2007/11/16/161006.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>