給出了 Spring1.2舊式AOP (基于dtd)實(shí)現(xiàn)的示例。
雖然在Spring 3中受支持,但advice使用在下一頁將要學(xué)習(xí)的將Spring aop與AspectJ一起使用。
spring1.2舊式aop實(shí)現(xiàn)中支持4種類型的Advice。
Before Advice,在實(shí)際方法調(diào)用之前執(zhí)行。 After Advice,在實(shí)際方法調(diào)用之后執(zhí)行。如果方法返回值,則在返回值后執(zhí)行。 Around Advice,它在實(shí)際方法調(diào)用之前和之后執(zhí)行。 Throws Advice,如果實(shí)際方法引發(fā)異常,則執(zhí)行該Advice。
讓我們通過以下圖表了解Advice層次結(jié)構(gòu):
所有都是aop中的接口。
MethodBeforeAdvice 接口擴(kuò)展了 BeforeAdvice 接口。
AfterReturningAdvice 接口擴(kuò)展了 AfterAdvice 接口。
ThrowsAdvice 接口擴(kuò)展 AfterAdvice 接口。
MethodInterceptor 接口擴(kuò)展 Interceptor 接口。它用于Advice周圍。
1、MethodBeforeAdvice示例
創(chuàng)建一個(gè)包含實(shí)際業(yè)務(wù)邏輯的類。
文件: A.java
package com.nhooo; public class A { public void m(){System.out.println("actual business logic");} }
現(xiàn)在,創(chuàng)建實(shí)現(xiàn)MethodBeforeAdvice接口的顧問程序類。
文件: BeforeAdvisor.java
package com.nhooo; import java.lang.reflect.Method; import org.springframework.aop.MethodBeforeAdvice; public class BeforeAdvisor implements MethodBeforeAdvice{ @Override public void before(Method method, Object[] args, Object target)throws Throwable { System.out.println("additional concern before actual logic"); } }
在xml文件中,創(chuàng)建3個(gè)bean,一個(gè)用于A類,第二個(gè)用于Advisor類,第三個(gè)用于 ProxyFactoryBean 類。
文件: applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"> <bean id="obj" class="com.nhooo.A"></bean> <bean id="ba" class="com.nhooo.BeforeAdvisor"></bean> <bean id="proxy" class="org.springframework.aop.framework.ProxyFactoryBean"> <property name="target" ref="obj"></property> <property name="interceptorNames"> <list> <value>ba</value> </list> </property> </bean> </beans>
理解ProxyFactoryBean類:
ProxyFactoryBean 類由Spring Famework提供。它包含2個(gè)屬性target和interceptorNames。 A類的實(shí)例將被視為目標(biāo)對(duì)象,顧問類的實(shí)例將被視為攔截器。您需要像上面給出的xml文件中那樣將顧問程序?qū)ο笞鳛榱斜韺?duì)象傳遞。
ProxyFactoryBean類的編寫如下:
public class ProxyFactoryBean{ private Object target; private List interceptorNames; //getters and setters }
現(xiàn)在,讓我們調(diào)用實(shí)際方法。
文件: Test.java
package com.nhooo; import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.xml.XmlBeanFactory; import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.Resource; public class Test { public static void main(String[] args) { Resource r=new ClassPathResource("applicationContext.xml"); BeanFactory factory=new XmlBeanFactory(r); A a=factory.getBean("proxy",A.class); a.m(); } }
輸出
additional concern before actual logic actual business logic
在MethodBeforeAdvice中打印其他信息,我們可以打印其他信息,例如方法名稱,方法參數(shù),目標(biāo)對(duì)象,目標(biāo)對(duì)象類名稱,代理類等。
您只需要更改兩個(gè)類BeforeAdvisor.java和Test.java。
文件: BeforeAdvisor.java
package com.nhooo; import java.lang.reflect.Method; import org.springframework.aop.MethodBeforeAdvice; public class BeforeAdvisor implements MethodBeforeAdvice{ @Override public void before(Method method, Object[] args, Object target)throws Throwable { System.out.println("additional concern before actual logic"); System.out.println("method info:"+method.getName()+" "+method.getModifiers()); System.out.println("argument info:"); for(Object arg:args) System.out.println(arg); System.out.println("target Object:"+target); System.out.println("target object class name: "+target.getClass().getName()); } }
文件: Test.java
package com.nhooo; import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.xml.XmlBeanFactory; import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.Resource; public class Test { public static void main(String[] args) { Resource r=new ClassPathResource("applicationContext.xml"); BeanFactory factory=new XmlBeanFactory(r); A a=factory.getBean("proxy",A.class); System.out.println("proxy class name: "+a.getClass().getName()); a.m(); } }
輸出
proxy class name: com.nhooo.A$EnhancerByCGLIB$409872b1 additional concern before actual logic method info:m 1 argument info: target Object:com.nhooo.A@11dba45 target object class name: com.nhooo.A actual business logic
AfterReturningAdvice示例
創(chuàng)建一個(gè)包含實(shí)際業(yè)務(wù)邏輯的類。
文件: A.java
與前面的示例相同。
現(xiàn)在,創(chuàng)建實(shí)現(xiàn)AfterReturningAdvice接口的顧問類。
文件: AfterAdvisor.java
package com.nhooo; import java.lang.reflect.Method; import org.springframework.aop.AfterReturningAdvice; public class AfterAdvisor implements AfterReturningAdvice{ @Override public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable { System.out.println("additional concern after returning advice"); } }
像前面的示例一樣創(chuàng)建xml文件,您只需要在此處更改顧問程序類。
文件: applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"> <bean id="obj" class="com.nhooo.A"></bean> <bean id="ba" class="com.nhooo.AfterAdvisor"></bean> <bean id="proxy" class="org.springframework.aop.framework.ProxyFactoryBean"> <property name="target" ref="obj"></property> <property name="interceptorNames"> <list> <value>ba</value> </list> </property> </bean> </beans>
文件: Test.java
與前面的示例相同。
輸出
actual business logic additional concern after returning advice
3)MethodInterceptor(AroundAdvice)示例
創(chuàng)建一個(gè)包含實(shí)際業(yè)務(wù)邏輯的類。
文件: A。 java
與前面的示例相同。
現(xiàn)在,創(chuàng)建實(shí)現(xiàn)MethodInterceptor接口的顧問類。
文件: AroundAdvisor.java
package com.nhooo; import org.aopalliance.intercept.MethodInterceptor; import org.aopalliance.intercept.MethodInvocation; public class AroundAdvisor implements MethodInterceptor{ @Override public Object invoke(MethodInvocation mi) throws Throwable { Object obj; System.out.println("additional concern before actual logic"); obj=mi.proceed(); System.out.println("additional concern after actual logic"); return obj; } }
像前面的示例一樣創(chuàng)建xml文件,您只需要在此處更改顧問程序類。
文件: applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"> <bean id="obj" class="com.nhooo.A"></bean> <bean id="ba" class="com.nhooo.AroundAdvisor"></bean> <bean id="proxy" class="org.springframework.aop.framework.ProxyFactoryBean"> <property name="target" ref="obj"></property> <property name="interceptorNames"> <list> <value>ba</value> </list> </property> </bean> </beans>
文件: Test.java
與前面的示例相同。
輸出
additional concern before actual logic actual business logic additional concern after actual logic
4、ThrowsAdvice示例
創(chuàng)建一個(gè)包含實(shí)際業(yè)務(wù)邏輯的類。
文件: Validator.java
package com.nhooo; public class Validator { public void validate(int age)throws Exception{ if(age<18){ throw new ArithmeticException("Not Valid Age"); } else{ System.out.println("vote confirmed"); } } }
現(xiàn)在,創(chuàng)建實(shí)現(xiàn)ThrowsAdvice接口的顧問程序類。
文件: ThrowsAdvisor.java
package com.nhooo; import org.springframework.aop.ThrowsAdvice; public class ThrowsAdvisor implements ThrowsAdvice{ public void afterThrowing(Exception ex){ System.out.println("additional concern if exception occurs"); } }
像前面的示例一樣創(chuàng)建xml文件,您只需要更改Validator類和Advisor類。
文件: applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"> <bean id="obj" class="com.nhooo.Validator"></bean> <bean id="ba" class="com.nhooo.ThrowsAdvisor"></bean> <bean id="proxy" class="org.springframework.aop.framework.ProxyFactoryBean"> <property name="target" ref="obj"></property> <property name="interceptorNames"> <list> <value>ba</value> </list> </property> </bean> </beans>
文件: Test.java
package com.nhooo; import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.xml.XmlBeanFactory; import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.Resource; public class Test { public static void main(String[] args) { Resource r=new ClassPathResource("applicationContext.xml"); BeanFactory factory=new XmlBeanFactory(r); Validator v=factory.getBean("proxy",Validator.class); try{ v.validate(12); }catch(Exception e){e.printStackTrace();} } }
輸出
java.lang.ArithmeticException: Not Valid Age additional concern if exception occurs at com.nhooo.Validator.validate(Validator.java:7) at com.nhooo.Validator$FastClassByCGLIB$562915cf.invoke(<generated>) at net.sf.cglib.proxy.MethodProxy.invoke(MethodProxy.java:191) at org.springframework.aop.framework.Cglib2AopProxy$CglibMethodInvocation.invoke Joinpoint(Cglib2AopProxy.java:692) at org.springframework.aop.framework.ReflectiveMethodInvocation. proceed(ReflectiveMethodInvocation.java:150) at org.springframework.aop.framework.adapter.ThrowsAdviceInterceptor. invoke(ThrowsAdviceInterceptor.java:124) at org.springframework.aop.framework.ReflectiveMethodInvocation. proceed(ReflectiveMethodInvocation.java:172) at org.springframework.aop.framework.Cglib2AopProxy$DynamicAdvisedInterceptor. intercept(Cglib2AopProxy.java:625) at com.nhooo.Validator$EnhancerByCGLIB$4230ed28.validate(<generated>) at com.nhooo.Test.main(Test.java:15)