spring aop 配置 原

  • spring aop

       面向切面編程(AOP),是軟件編程思想發展到一定階段的產物,是對面向對象編程(OOP)的有益補充。AOP一般適用於具有橫切邏輯的場合,如訪問控制、事務管理、性能監測等。
        面向切面編程,簡單的說,就是在不改變源程序的基礎上爲代碼段增加新的功能,對代碼進行增強處理,它的設計思想來源於代理設計模式。

瞭解之後需要知道以下概念:

        1.增強類型:
                前置增強(通知),在在原方法執行之前進行處理,同理還有後置增強、環繞增強、異常拋出增強、最終增強等。
        2.連接點(Joinpoint):
                程序執行的某個特定位置:如類某個方法調用前、調用後、方法拋出異常後等。
        3.切點(Pointcut):
                每個類都擁有多個連接點:類的所有方法實際上都是連接點,即連接點是程序類中客觀存在的事務。AOP 通過切點定位到特定的連接點。類比:連接點相當於數據庫中的記錄,切點相當於查詢條件。切點和連接點不是一對一的關係,一個切點匹配多個連接點,切點通過 org.springframework.aop.Pointcut 接口進行描述,它使用類和方法作爲連接點的查詢條件。

需求:UserDao 接口(根據id 獲取用戶信息)

/**
 * @note 用戶Dao
 * @author liuh
 * */
public interface UserDao {

	/**
	 * @note 根據用戶id 獲取用戶
	 * @author liuh
	 * */
	public User getUser(int id);
}

UserDaoImpl 實現

/**
 * @note 用戶UserDao 接口實現
 * @author liuh
 * */
public class UserDaoImpl implements UserDao{

	/**
	 * @note 根據id 獲取用戶
	 * @author liuh
	 * */
	@Override
	public User getUser(int id){
		System.out.println("模擬根據【id】獲取用戶信息實現");
		User u=new User();
		u.setId(id);
		u.setName("hello");
		return u;
	}

}
  • 基於xml配置實現spring aop增強

1.前置增強

(1)創建UserLogger類,新增before_log方法:

/**
 * @note 用戶增強類
 * @author liuh
 * */
public class UserLogger {

	/**
	 * @note 前置
	 * */
	public void before_log(JoinPoint jp){
		System.out.println("調用"+jp.getTarget()+"的方法:"+jp.getSignature().getName()+"參數:"+jp.getArgs());
	}
}

(2)配置增強實現

	<!-- 用戶Dao 實現Bean -->
	<bean id="aop_userImpl" class="com.liuh.aop.UserDaoImpl"></bean>
	<!-- 用戶增強 實現 Bean -->
	<bean id="use_log" class="com.liuh.aop.UserLogger"></bean>
	<!-- aop stat -->
	<aop:config>
		<!-- 切點 -->
		<aop:pointcut expression="execution(public * getUser(..))" id="useDao_point"/>
		<!-- 增強 -->
		<aop:aspect ref="use_log">
			<!-- 前置增強 -->
			<aop:before method="before_log" pointcut-ref="useDao_point"/>
		</aop:aspect>
	</aop:config>
	<!-- aop end -->

2.後置增強

(1)在新增UserLogger類 afterReturn_log方法

	/**
	 * @note 後置返回值
	 * */
	public void afterReturn_log(JoinPoint jp,Object obj){
		System.out.println("調用"+jp.getTarget()+"的方法:"+jp.getSignature().getName()+"參數:"+jp.getArgs()+"返回值:"+((User)obj).getName());
	}

(2)後置增強配置

    <!-- 用戶Dao 實現Bean -->
	<bean id="aop_userImpl" class="com.liuh.aop.UserDaoImpl"></bean>
	<!-- 用戶增強 實現 Bean -->
	<bean id="use_log" class="com.liuh.aop.UserLogger"></bean>
	<!-- aop stat -->
	<aop:config>
		<!-- 切點 -->
		<aop:pointcut expression="execution(public * getUser(..))" id="useDao_point"/>
		<!-- 增強 -->
		<aop:aspect ref="use_log">
			<!-- 後置增強 返回值 -->
			<aop:after-returning method="afterReturn_log" pointcut-ref="useDao_point" returning="obj"/>
		</aop:aspect>
	</aop:config>
	<!-- aop end -->

3.環繞增強

(1)在新增UserLogger類 round_log方法

	/**
	 * @note 環繞
	 * */
	public void round_log(ProceedingJoinPoint jp){
		System.out.println("前置調用"+jp.getTarget()+"的方法:"+jp.getSignature().getName()+"參數:"+jp.getArgs());
		Object obj=null;
		try {
			obj =jp.proceed();
		} catch (Throwable e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		System.out.println("後置調用"+jp.getTarget()+"的方法:"+jp.getSignature().getName()+"參數:"+jp.getArgs()+"返回值:"+((User)obj).getId());
	}

(2)環繞配置

    <!-- 用戶Dao 實現Bean -->
	<bean id="aop_userImpl" class="com.liuh.aop.UserDaoImpl"></bean>
	<!-- 用戶增強 實現 Bean -->
	<bean id="use_log" class="com.liuh.aop.UserLogger"></bean>
	<!-- aop stat -->
	<aop:config>
		<!-- 切點 -->
		<aop:pointcut expression="execution(public * getUser(..))" id="useDao_point"/>
		<!-- 增強 -->
		<aop:aspect ref="use_log">
			<!-- 環繞 -->
			<aop:around method="round_log" pointcut-ref="useDao_point"/>
		</aop:aspect>
	</aop:config>
	<!-- aop end -->

4.異常增強(異常拋出增強方法)

(1)在新增UserLogger類 catch_log方法

	/**
	 * @note 異常增強
	 * */
	public void catch_log(JoinPoint jp,RuntimeException e){
		try {
			throw e;
		} catch (Exception e2) {
			System.out.println("處理該異常");
			// TODO: handle exception
		}
		System.out.println("異常調用"+jp.getTarget()+"的方法:"+jp.getSignature().getName()+"參數:"+jp.getArgs()+"異常:"+e.getMessage());
	}

(2)異常增強配置

    <!-- 用戶Dao 實現Bean -->
	<bean id="aop_userImpl" class="com.liuh.aop.UserDaoImpl"></bean>
	<!-- 用戶增強 實現 Bean -->
	<bean id="use_log" class="com.liuh.aop.UserLogger"></bean>
	<!-- aop stat -->
	<aop:config>
		<!-- 切點 -->
		<aop:pointcut expression="execution(public * getUser(..))" id="useDao_point"/>
		<!-- 增強 -->
		<aop:aspect ref="use_log">
			<!-- 異常增強 -->
			<aop:after-throwing method="catch_log" pointcut-ref="useDao_point" throwing="e"/>
		</aop:aspect>
	</aop:config>
	<!-- aop end -->

5.最終增強

        我們知道,如果在目標方法中拋出了異常,就不會執行後續的後置增強。在AspectJ中爲我們提供了一種最終增強,無論是否出了異常都會執行,類似於try-catch中的finally塊,一般用於釋放資源

(1)在新增UserLogger類 after_log方法

	/**
	 * @note 最終
	 * */
	public void after_log(JoinPoint jp){
		System.out.println("最終增強調用"+jp.getTarget()+"的方法:"+jp.getSignature().getName()+"參數:"+jp.getArgs());
	}

(2)最終增強配置

    <!-- 用戶Dao 實現Bean -->
	<bean id="aop_userImpl" class="com.liuh.aop.UserDaoImpl"></bean>
	<!-- 用戶增強 實現 Bean -->
	<bean id="use_log" class="com.liuh.aop.UserLogger"></bean>
	<!-- aop stat -->
	<aop:config>
		<!-- 切點 -->
		<aop:pointcut expression="execution(public * getUser(..))" id="useDao_point"/>
		<!-- 增強 -->
		<aop:aspect ref="use_log">
			<!-- 最終增強 -->
			<aop:after method="after_log" pointcut-ref="useDao_point"/>
		</aop:aspect>
	</aop:config>
	<!-- aop end -->
  • 測試
public class AopTest {

	public static void main(String[] args) {
		ApplicationContext ctx=new ClassPathXmlApplicationContext("applicationContext.xml");
		UserDao userD=(UserDao)ctx.getBean("aop_userImpl");
		userD.getUser(1123);
	}
}

 

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