spring aop淺析

         spring最核心的也就屬ioc和aop了,雖然知道ioc和aop的原理,但在項目中只用到了ioc,aop沒用到,所以這裏對aop進行一下總結。

spring aop英文全名Aspect Orient Programming 也就是面向方面編程,它是對面向對象編程的一種補充,被專門用來處理系統中分佈於各個模塊中的交叉關注點的問題,例如在javaee應用中aop常被用來處理一些具有橫切性質的系統級服務如事務管理,安全檢查,緩存,對象池管理等。AOP框架通過自動生成代理來實現業務的擴充,spring AOP有兩種生成代理的方式,一種是JDK的動態代理,一中時CGLIB的,這兩種的區別在於如果目標對象實現了接口,spring AOP就會使用jdk的動態代理,如果目標對象沒有實現接口,它就會使用CGLIB的。關於jdk的動態代理在設計模式系列的文章中已經詳述,這裏就不多說,下面我們來使用spring aop來完成功能的擴充。

首先導入spring的jar包,這裏直接截圖:

因爲我是先把spring和struts2整合了一下才測試的,所以裏面包含了一些struts2的jar包,這裏只看spring 的

實現aop必須的包:

1、aopalliance.jar

AOP Alliance(http://aopalliance.sourceforge.net/) 是個聯合的開源協作組織,在多個項目間進行協作以期提供一套標準的AOP Java接口(interface)。 Spring AOP就是基於AOP Alliance標準API實現的。如果你打算使用Spring的AOP或基於AOP的任何特性,只需這個JAR文件。

2、aspectjrt.jar和aspectjweaver.jar,如果你的目標對象沒有實現目標接口,你還得導入cglib的jar包,這裏只是測試實現接口的目標對象,所以不導入了,其他一些必要的spring包比如核心包等大家應該都知道。

接下來我們在配置文件spring.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:aop="http://www.springframework.org/schema/aop" 
xsi:schemaLocation="
http://www.springframework.org/schema/beans 
classpath:/org/springframework/beans/factory/xml/spring-beans-3.0.xsd 
http://www.springframework.org/schema/context 
classpath:/org/springframework/context/config/spring-context-3.0.xsd
http://www.springframework.org/schema/aop 
classpath:/org/springframework/aop/config/spring-aop-3.0.xsd
">
	<!-- 指定自動搜索 Bean 組件、自動搜索方面類 -->
	<context:component-scan base-package="com.dxy.service.impl,com.dxy.test"> 
	 	<context:include-filter type="annotation" expression="org.aspectj.lang.annotation.Aspect"/> 
	</context:component-scan>
	<!-- 啓動@Aspect支持 -->
	<aop:aspectj-autoproxy/>
	
</beans>


對於spring.xml文件中的以這樣的方式引入xsd文件,是因爲網速慢,所以解析xsd文件出錯,不得不用本地的xsd文件,具體原因見:

http://blog.csdn.net/legendj/article/details/9950963

接着創建接口UserServiceI.java:

package com.dxy.service;

public interface UserServiceI {
	
	public String add();
}

創建實現:

package com.dxy.service.impl;

import org.springframework.stereotype.Service;

import com.dxy.service.UserServiceI;
@Service("userService")
public class UserServiceImpl implements UserServiceI {

	@Override
	public void add() {
		System.out.println("hello world");
	}
	
}

接着定義一個方面,並使用spring AOP的Around增強處理:

package com.dxy.test;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
//定義一個方面
@Aspect
public class AroundAdviceTest {
	@Around("execution(* com.dxy.service.impl.*.*(..))")
	public void log(ProceedingJoinPoint jp) {
		System.out.println("test add start");
		try {
			jp.proceed();
		} catch (Throwable e) {
			e.printStackTrace();
		}
		System.out.println("test add end");
	}
}

ok,我們在客戶端可以調用了:

package com.dxy.test;

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

import com.dxy.service.UserServiceI;

public class MainTest {
	
	public static void main(String[] args) {
		ApplicationContext ac = new ClassPathXmlApplicationContext("classpath:spring.xml");
		UserServiceI userService = (UserServiceI)ac.getBean("userService",UserServiceI.class);
		System.out.println(userService.getClass());
		userService.add();
	}
}

運行結果:

這樣就成功的在add方法前後加上了日誌處理,我們通過打印userService的類型得到的是一個代理類class $Proxy8如果使用cglib的話就會生成一個cglib的代理。通過以上示例我們可以知道AOP 代理其實是由 AOP 框架動態生成的一個對象,該對象可作爲目標對象使用。AOP 代理包含了目標對象的全部方法,但 AOP 代理中的方法與目標對象的方法存在差異:AOP 方法在特定切入點添加了增強處理,並回調了目標對象的方法。

 

 

 

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