除了依賴注入(DI),Spring Framework提供的另一個核心特性是面向方面的編程(AOP)。
除了依賴注入(DI),Spring Framework提供的另一個核心特性是面向方面的編程(AOP)。...
橫切關(guān)注點指的是應(yīng)用程序中的邏輯不能從其余的分解應(yīng)用程序并可能導(dǎo)致代碼重復(fù)和緊密耦合。
AOP是一個旨在提高模塊性的編程范例通過允許分離交叉關(guān)注點。
AOP是一個旨在提高模塊性的編程范例通過允許分離交叉關(guān)注點。...
Spring AOP框架在各方面模塊化橫切關(guān)注點。當(dāng)在Spring IoC容器中執(zhí)行一個方法時,Spring AOP可以劫持執(zhí)行方法,并在方法執(zhí)行之前或之后添加額外的功能。
AOP具有自己特定的概念和術(shù)語集。
以下是AOP的核心概念:
Spring AOP有四種類型的建議。
建議是在方法執(zhí)行之前或之后采取的動作。
將以下新的依賴關(guān)系添加到POM.xml中進(jìn)行AOP編碼。
<dependency> <groupId>cglib</groupId> <artifactId>cglib</artifactId> <version>2.2.2</version> </dependency>
以下代碼定義了打印機(jī)服務(wù)的Java bean。
package com.hgci.cnmon; public class PrinterService { private String name; private String url; public void setName(String name) { this.name = name; } public void setUrl(String url) { this.url = url; } public void printName() { System.out.println("Printer Name : " + this.name); } public void printURL() { System.out.println("Printer URL : " + this.url); } public void printThrowException() { throw new IllegalArgumentException(); } }
這里是用于bean配置的Spring-Customer.xml文件。
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"> <bean id="myService" class="com.hgci.cnmon.PrinterService"> <property name="name" value="printerName" /> <property name="url" value="http://www.hgci.cn" /> </bean> </beans>
以下是運行上面代碼的主類。
package com.hgci.cnmon; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class App { public static void main(String[] args) { ApplicationContext appContext = new ClassPathXmlApplicationContext( new String[] { "SpringBeans.xml" }); PrinterService cust = (PrinterService) appContext.getBean("myService"); cust.printName(); cust.printURL(); try { cust.printThrowException(); } catch (Exception e) { } } }
輸出
下面的代碼顯示了如何添加Before通知。
A Before在方法執(zhí)行之前執(zhí)行。
首先,創(chuàng)建一個實現(xiàn)MethodBeforeAdvice接口的類。
package com.hgci.cnmon; import java.lang.reflect.Method; import org.springframework.aop.MethodBeforeAdvice; public class AOPBeforeMethod implements MethodBeforeAdvice { @Override public void before(Method method, Object[] args, Object target) throws Throwable { System.out.println("AOPBeforeMethod : Before method call."); } }
然后,我們在xml配置文件中創(chuàng)建AOPBeforeMethod bean。
<bean id="aopBeforeMethodBean" class="com.java2s.aop.AOPBeforeMethod" />
要使用 AOPBeforeMethod
類,我們必須使用安裝它 org.springframework.aop.framework.ProxyFactoryBean
,如下所示。
<bean id="myServiceProxy" class="org.springframework.aop.framework.ProxyFactoryBean"> <property name="target" ref="myService" /> <property name="interceptorNames"> <list> <value>aopBeforeMethodBean</value> </list> </property> </bean>
完整的源代碼
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"> <bean id="myService" class="com.hgci.cnmon.PrinterService"> <property name="name" value="printerName" /> <property name="url" value="http://www.hgci.cn" /> </bean> <bean id="aopBeforeMethodBean" class="com.hgci.cnmon.AOPBeforeMethod" /> <bean id="myServiceProxy" class="org.springframework.aop.framework.ProxyFactoryBean"> <property name="target" ref="myService" /> <property name="interceptorNames"> <list> <value>aopBeforeMethodBean</value> </list> </property> </bean> </beans>
再次運行main函數(shù)。
從結(jié)果我們可以看到AOPBeforeMethod“的before()方法在每個myService的方法之前執(zhí)行。
下面的代碼顯示了如何使用After返回通知。返回通知后,將在方法返回結(jié)果后執(zhí)行。
首先,創(chuàng)建一個實現(xiàn)AfterReturningAdvice接口的類。
package com.hgci.cnmon; import java.lang.reflect.Method; import org.springframework.aop.AfterReturningAdvice; public class AOPAfterMethod implements AfterReturningAdvice { @Override public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable { System.out.println("AOPAfterMethod : After method call."); } }
然后,在 AOPAfterMethod
類中安裝Bean配置文件。
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"> <bean id="myService" class="com.hgci.cnmon.PrinterService"> <property name="name" value="printerName" /> <property name="url" value="http://www.hgci.cn" /> </bean> <bean id="aopAfterMethodBean" class="com.hgci.cnmon.AOPAfterMethod" /> <bean id="myServiceProxy" class="org.springframework.aop.framework.ProxyFactoryBean"> <property name="target" ref="myService" /> <property name="interceptorNames"> <list> <value>aopAfterMethodBean</value> </list> </property> </bean> </beans>
再次運行main函數(shù)。 這里是輸出。
從結(jié)果我們可以看到AOPAfterMethod的“afterReturning()方法在每個myService的方法返回結(jié)果之后執(zhí)行。
下面的代碼顯示了如何使用After拋出的建議。拋出后拋出的通知會在方法拋出異常后執(zhí)行。
第一,創(chuàng)建一個實現(xiàn)ThrowsAdvice接口的類,并創(chuàng)建一個afterThrowing方法來劫持IllegalArgumentException異常。
package com.hgci.cnmon; import org.springframework.aop.ThrowsAdvice; public class AOPThrowException implements ThrowsAdvice { public void afterThrowing(IllegalArgumentException e) throws Throwable { System.out.println("AOPThrowException : Throw exception call."); } }
然后,在Bean配置文件中安裝 AOPThrowException
。
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"> <bean id="myService" class="com.hgci.cnmon.PrinterService"> <property name="name" value="printerName" /> <property name="url" value="http://www.hgci.cn" /> </bean> <bean id="aopThrowExceptionBean" class="com.hgci.cnmon.AOPThrowException" /> <bean id="myServiceProxy" class="org.springframework.aop.framework.ProxyFactoryBean"> <property name="target" ref="myService" /> <property name="interceptorNames"> <list> <value>aopThrowExceptionBean</value> </list> </property> </bean> </beans>
運行代碼,這里是輸出。
Printer Name : printerName Printer URL : http://www.hgci.cn AOPThrowException : Throw exception call.
從結(jié)果我們可以看到Spring IoC容器運行AOPThrowException的s afterThrowing() 方法,當(dāng)myService的方法拋出異常。
以下代碼顯示如何使用Around建議。周圍的建議綜合了上面的所有三個建議,并在方法執(zhí)行期間執(zhí)行。
首先,創(chuàng)建一個實現(xiàn)MethodInterceptor接口的類。
public Object invoke(MethodInvocation methodInvocation)throws Throwable方法是為每個方法調(diào)用,我們必須調(diào)用“methodInvocation.proceed();" 以運行原始方法,否則原方法將不會運行。
package com.hgci.cnmon; import java.util.Arrays; import org.aopalliance.intercept.MethodInterceptor; import org.aopalliance.intercept.MethodInvocation; public class AOPAroundMethod implements MethodInterceptor { @Override public Object invoke(MethodInvocation methodInvocation) throws Throwable { System.out.println("Method name : " + methodInvocation.getMethod().getName()); System.out.println("Method arguments : " + Arrays.toString(methodInvocation.getArguments())); System.out.println("AOPAroundMethod : Before method call."); try { // proceed to original method call Object result = methodInvocation.proceed(); // same with AfterReturningAdvice System.out.println("AOPAroundMethod : after call."); return result; } catch (IllegalArgumentException e) { System.out.println("AOPAroundMethod : Throw exception call."); throw e; } } }
這里是xml Bean配置文件來安裝Around Advice AOP。
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"> <bean id="myService" class="com.hgci.cnmon.PrinterService"> <property name="name" value="printerName" /> <property name="url" value="http://www.hgci.cn" /> </bean> <bean id="aopAroundMethodBean" class="com.hgci.cnmon.AOPAroundMethod" /> <bean id="myServiceProxy" class="org.springframework.aop.framework.ProxyFactoryBean"> <property name="target" ref="myService" /> <property name="interceptorNames"> <list> <value>aopAroundMethodBean</value> </list> </property> </bean> </beans>
運行main函數(shù),這里是輸出。
更多建議: