﻿<?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-JAVA流通桥-文章分类-SPRING文章</title><link>http://www.blogjava.net/zhuyan/category/51859.html</link><description>JAVA启发者</description><language>zh-cn</language><lastBuildDate>Sun, 03 Jun 2012 01:08:39 GMT</lastBuildDate><pubDate>Sun, 03 Jun 2012 01:08:39 GMT</pubDate><ttl>60</ttl><item><title>Spring AOP介绍</title><link>http://www.blogjava.net/zhuyan/articles/379801.html</link><dc:creator>朱岩</dc:creator><author>朱岩</author><pubDate>Sat, 02 Jun 2012 05:53:00 GMT</pubDate><guid>http://www.blogjava.net/zhuyan/articles/379801.html</guid><wfw:comment>http://www.blogjava.net/zhuyan/comments/379801.html</wfw:comment><comments>http://www.blogjava.net/zhuyan/articles/379801.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/zhuyan/comments/commentRss/379801.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/zhuyan/services/trackbacks/379801.html</trackback:ping><description><![CDATA[<div>&nbsp; Spring AOP介绍 <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></div><img src ="http://www.blogjava.net/zhuyan/aggbug/379801.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/zhuyan/" target="_blank">朱岩</a> 2012-06-02 13:53 <a href="http://www.blogjava.net/zhuyan/articles/379801.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>