Java中AOP技術詳解

 

AOP是Aspect Oriented Programming的縮寫,意思是面向方面編程,與OOP(Object Oriented Programming)面向對象編程對等,都是一種編程思想。
從OOP角度分析,我們關注業務的處理邏輯,是屬於縱向的行爲,從AOP角度分析,我們關注對象行爲發生時的問題,是屬於橫向的行爲。

AOP 作用:
1	監控函數的調用
2	捕獲異常發生

實際應用在:事務、安全、日誌等橫切關注。

兩種實現AOP的方式:
	1,JDK提供的動態代理實現 
//接口
public interface UserBean
{
	void getUser();
	void addUser();
	void updateUser();
	void deleteUser();
}
//原始實現類
public class UserBeanImpl implements UserBean
{
	private String user = null;
	public UserBeanImpl()
	{		
	}	
	public UserBeanImpl(String user)
	{
		this.user = user;
	}	
	public String getUserName()
	{
		return user;
	}	
	public void getUser()
	{
		System.out.println("this is getUser() method!");
	}

	public void setUser(String user)
	{
		this.user = user;
		System.out.println("this is setUser() method!");
	}
	public void addUser()
	{
		System.out.println("this is addUser() method!");
	}
	
	public void updateUser()
	{
		System.out.println("this is updateUser() method!");
	}	
	public void deleteUser()
	{
		System.out.println("this is deleteUser() method!");  
	}		
}
//代理類
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import com.cignacmc.finance.bean.UserBeanImpl;

public class UserBeanProxy implements InvocationHandler
{
	private Object targetObject;
	
	public  UserBeanProxy(Object targetObject)
	{
		this.targetObject = targetObject;		
	}
	
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
	{
		UserBeanImpl userBean = (UserBeanImpl) targetObject;
		String userName = userBean.getUserName();
		Object result = null;
		
		//權限判斷
		if(userName != null && !"".equals(userName))
		{
			result = method.invoke(targetObject, args);
		}
		
		return result;
	}
}

//測試類
import java.lang.reflect.Proxy;

import com.cignacmc.finance.bean.UserBean;
import com.cignacmc.finance.bean.UserBeanImpl;
import com.cignacmc.finance.proxy.UserBeanProxy;

public class ProxyExe
{
	public static void main(String[] args)
	{
		System.out.println("Proved.............");
		UserBeanImpl targetObject = new UserBeanImpl("Bob Liang");		
		UserBeanProxy proxy = new UserBeanProxy(targetObject);
		//生成代理對象		
		UserBean object = (UserBean)Proxy.newProxyInstance(targetObject.getClass().getClassLoader(), 
				targetObject.getClass().getInterfaces(), proxy);
		object.addUser();
		
		System.out.println("NO Proved.............");
		targetObject = new UserBeanImpl();		
		proxy = new UserBeanProxy(targetObject);
		//生成代理對象		
		object = (UserBean)Proxy.newProxyInstance(targetObject.getClass().getClassLoader(), 
				targetObject.getClass().getInterfaces(), proxy);
		object.addUser();
				
	}
}

輸出:
Proved.............
this is addUser() method!
NO Proved.............

從上面這個例子可以成功攔截了調用的方法addUser()並對其做了相應的處理 

	2, 通過cglib創建代理類, 好處是不要求我們的目標對象實現接口
//原始類
public class ClientBean
{
	private String name = null;

	public ClientBean()
	{

	}

	public ClientBean(String name)
	{
		this.name = name;
	}

	public void addClient()
	{
		System.out.println("this is addClient() method!");
	}

	public void deleteClient()
	{
		System.out.println("this is deleteClient() method!");
	}

	public void getClient()
	{
		System.out.println("this is getClient() method!");
	}

	public void updateClient()
	{
		System.out.println("this is updateClient() method!");
	}

	public String getClientName()
	{
		return name;
	}

	public void setClientName(String name)
	{
		this.name = name;
	}
}
//代理類
import java.lang.reflect.Method;

import com.cignacmc.finance.bean.ClientBean;

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

public class CGLibProxy implements MethodInterceptor
{
	private Object targetObject;
	
	public Object createProxyObject(Object targetObject)
	{
		this.targetObject = targetObject;
		Enhancer enhancer = new Enhancer();
		enhancer.setSuperclass(this.targetObject.getClass());
		enhancer.setCallback(this);
		return enhancer.create();
	}
	
	public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable
	{
		ClientBean clientBean = (ClientBean)targetObject;
		String userName = clientBean.getClientName();
		Object result = null;
		
		if(userName != null && !"".equals(userName))
		{
			result = method.invoke(targetObject, args);
		}
		return result;
	}
}
//測試類
import java.lang.reflect.Proxy;

import com.cignacmc.finance.bean.ClientBean;
import com.cignacmc.finance.bean.UserBean;
import com.cignacmc.finance.bean.UserBeanImpl;
import com.cignacmc.finance.proxy.CGLibProxy;
import com.cignacmc.finance.proxy.UserBeanProxy;

public class ProxyExe
{
	public static void main(String[] args)
	{	
		System.out.println(".............CGLIB Proxy....................");
		System.out.println("Proved....................");
		CGLibProxy cproxy = new CGLibProxy();
		ClientBean clientBean = (ClientBean)cproxy.createProxyObject(new ClientBean("Bob Liang"));
		clientBean.addClient();
		
		System.out.println("NO Proved....................");
		cproxy = new CGLibProxy();
		clientBean = (ClientBean)cproxy.createProxyObject(new ClientBean());
		clientBean.addClient();
				
	}
}

輸出:
.............CGLIB Proxy....................
Proved....................
this is addClient() method!
NO Proved....................


切面(Aspect):對橫切關注點的抽象(類似類對對象的抽象) 
連接點(JoinPoint):被攔截到的點,泛指方法 
切入點(CutPoint):對哪些連接點進行攔截的定義 
通知(Advice):在特定的連接點,AOP框架執行的動作.前置/後置/例外/最終/環繞通知(調用方法之前執行,全部執行完畢之後) 
引入(Introduction): 添加方法或字段到被通知的類。 Spring允許引入新的接口到任何被通知的對象。例如,你可以使用一個引入使任何對象實現 IsModified接口,來簡化緩存。 
目標對象(Target Object): 包含連接點的對象。也被稱作 被通知或被代理對象。 
AOP代理(AOP Proxy): AOP框架創建的對象,包含通知。 在Spring中,AOP代理可以是JDK動態代理或者CGLIB代理。 
織入(Weaving): 組裝方面來創建一個被通知對象。這可以在編譯時 完成(例如使用AspectJ編譯器),也可以在運行時完成。Spring和其他純Java AOP框架一樣, 在運行時完成織入。 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章