Spring學習-----AOP(1)

前面已經學過了bean的相關知識,對bean的配置方法也有了一定的瞭解。下面來學習Spring中一個重要的知識點AOP編程,這些知識點都是根據韓順平老師的視頻總結而來,雖然簡單,但是作爲入門瞭解還是不錯的。不過想要真正的應用到項目中,還需要進行深一步的學習。


  1. AOP的概念

        AOP(aspect oriented programming)面向切面編程,是對所有對象或是一類對象編程,核心是在不增加代碼的基礎上,還能增加功能。他所應用到的場景一般是將交叉功能(事務、日誌)提取出來。

         2、AOP術語

1、切面:要實現的交叉功能,是系統模塊化的一個切面或者領域(如日誌記錄等)

2、連接點:應用程序執行過程中插入切面的地點,可以是方法調用,異常拋出,或者要修改的字段。

3、通知:切面的實際實現,他通知系統新的行爲。如在日誌通知包含了實現日誌功能的代碼,向日志文件寫日誌。通知在連接點插入到應用系統中。

4、切入點:定義了通知應該應用在哪些連接點,通知可以應用到AOP框架支持的任何連接點。

5、引入:爲類添加新的方法和屬性

6、目標對象:被通知的對象,既可以是你編寫的類,也可以是第三方的類

7、代理:將通知應用到目標對象後創建的對象,應用系統的其他部分不用爲了支持代理對象而改變

8、織入:將切面應用到目標對象從而創建一個新的代理對象的過程。織入發生在目標對象生命週期的多個點上

編譯器:切面在目標對象編譯時織入,這需要一個特殊的編譯器

類裝載器:切面在目標對象那個被載入JVM是織入,這需要一個特殊的類載入器

運行期:切面在應用系統運行時織入

        3、配置步驟

步驟:

1、定義接口

2、編寫對象(被代理對象=目標對象)

3、編寫通知

4、bean.xml文件配置

1、配置被代理對象

2、配置通知

3、配置代理對象(是proxyFactoryBean實例)

a、配置被代理對象

b、配置代理接口集

c、把通知織入代理對象

下面我們來舉個例子,需求就是在調用UserBean 的sayHello()前利用前置通知完成日誌的書寫,利用環繞通知將sayHello方法包裹起來(然而現在並不能瞭解環繞通知的具體應用場景是什麼),調用完sayHello方法後,最後用後置通知釋放資源。


首先來看一下框架圖:




  1. 定義接口:
              package rogue.aop;

                  public interface TestSeverInter {

                  public void sayHello(); 

                 }


             package rogue.aop;

                 public interface TestSeverInter2 {

                 public void sayBye();

                }

                        

                      2.編寫目標對象

package rogue.aop;

public class SeverTest1 implements TestSeverInter,TestSeverInter2 {
	private String name;
	
	
	public String getName() {
		return name;
	}


	public void setName(String name) {
		this.name = name;
	}


	public void sayHello() {
		System.out.println("Hello"+name);
	}


	@Override
	public void sayBye() {
		System.out.println("Bye"+name);
		
	}

}

3、編寫通知

.package rogue.aop;

import java.lang.reflect.Method;

import org.springframework.aop.MethodBeforeAdvice;

public class MyMethodBeforeAdvice implements MethodBeforeAdvice {

	@Override
	/**
	 * method:被調用的方法的名字
	 * args:傳遞的參數
	 * target:目標對象(就是被調用的對象)
	 * 
	 */
	public void before(Method method, Object[] args, Object target)
			throws Throwable {
		// TODO Auto-generated method stub
		System.out.println("前置通知-通知日誌..."+method.getName());
	}

}

package rogue.aop;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;

public class MyMethodSurroundAdvice implements MethodInterceptor {

	@Override
	public Object invoke(MethodInvocation arg0) throws Throwable {
		// TODO Auto-generated method stub
		System.out.println("調用環繞通知前。。");
		arg0.proceed();
		System.out.println("調用環繞通知後。。");
		return null;
	}

}

package rogue.aop;

import java.lang.reflect.Method;

import org.springframework.aop.AfterReturningAdvice;

public class MyMethodAfterAdvice implements AfterReturningAdvice {

	@Override
	public void afterReturning(Object returnValue, Method method,
			Object[] args, Object target) throws Throwable {
		// TODO Auto-generated method stub
		System.out.println("關閉資源。。。");
	}

}

4、bean.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:context="http://www.springframework.org/schema/context"
		xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
	http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
		http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">

<!-- 配置被代理對象 -->
<bean id="SeverTest1" class="rogue.aop.SeverTest1">
  <property name="name" value="大帽子" />
</bean>

<!--配置通知-->
     <!-- 配置前置通知 -->
<bean id="MyMethodBeforeAdvice" class="rogue.aop.MyMethodBeforeAdvice" />
     <!-- 配置後置通知 -->
<bean id="MyMethodAfterAdvice" class="rogue.aop.MyMethodAfterAdvice" />
     <!-- 配置環繞通知 -->
<bean id="MyMethodSurroundAdvice" class="rogue.aop.MyMethodSurroundAdvice" />



<!-- 配置代理對象(也就是將被代理對象,接口和通知整合起來,配置在一起) -->
<bean id="proxyFactoryBean" class="org.springframework.aop.framework.ProxyFactoryBean">
       <!-- 第一步:將被代理對象織入到代理對象中 (name一定要是target)-->
<property name="target" ref="SeverTest1"></property>
       <!-- 第二步:將代理接口集織入到代理對象中 (name一定要是proxyInterfaces)-->
<property name="proxyInterfaces">
	<list>
		<value>rogue.aop.TestSeverInter</value><!-- 這裏應該是全限定名 -->
		<value>rogue.aop.TestSeverInter2</value>
	</list>
</property>

       <!-- 第三步:把通知織入到代理對象(name一定要是interceptorNames) -->
<property name="interceptorNames">
	<list>
	<!-- 相當於把MyMethodBeforeAdvice前置通知和代理對象關聯,也可以把通知看作攔截器  -->
		<value>MyMethodBeforeAdvice</value>
		<value>MyMethodAfterAdvice</value>
		<value>MyMethodSurroundAdvice</value>
	</list>
</property>


</bean>
</beans>

測試程序

package rogue.aop;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class app {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		ApplicationContext aContext = new ClassPathXmlApplicationContext("rogue/aop/aop.xml");
		
                //在這裏我們應該取proxyFactoryBean,因爲在這裏面有我們織入的通知,執行完通知後再執行正常的代碼
		TestSeverInter tS = (TestSeverInter) aContext.getBean("proxyFactoryBean");
		tS.sayHello();
		System.out.println("**********************************");
		
		((TestSeverInter2)tS).sayBye();
	}

}

結果截圖:





發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章