1. 程式人生 > 其它 >Spring AOP底層實現的兩種代理機制

Spring AOP底層實現的兩種代理機制

技術標籤:筆記

JDK\Cglib 的動態代理


1、dao

package com.test.dao;

import java.util.List;

import com.test.domain.User;

public interface UserDao {
	List<User> findAllUser();
	void save();
}

2、dao實現

package com.test.dao.impl;

import
java.util.List; import org.springframework.stereotype.Component; import org.springframework.stereotype.Repository; import com.test.dao.UserDao; import com.test.domain.User; //可以不寫名字;使用@Component註解就相當於在配置中寫了一個bean //@Component(value = "userdao") @Repository(value = "userdao") //@Repository //不寫value 那麼預設的就是當前類名的首字母小寫userDaolmpl
public class UserDaolmpl implements UserDao { public List<User> findAllUser() { // TODO Auto-generated method stub System.out.println("User"); return null; } public void save() { System.out.println("User"); } }

JDK 的動態代理(實現InvocationHandler)

  • 針對實現了介面的類產生代理.
package
springpro1; import java.lang.reflect.Method; import org.springframework.cglib.proxy.InvocationHandler; import org.springframework.cglib.proxy.Proxy; import com.test.dao.UserDao; public class MyJDKProxy implements InvocationHandler{ //將代理類傳進來,以建構函式的形式傳 private UserDao userDao; //有參構造 public MyJDKProxy(UserDao userDao) { this.userDao = userDao; } //編寫工具方法:生成代理: public UserDao createProxy(){ //用原來的真實類來產生它的代理類 UserDao userDaoProxy=(UserDao)Proxy.newProxyInstance(userDao.getClass().getClassLoader(),userDao.getClass().getInterfaces(), this); return userDaoProxy; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { if("save".equals(method.getName())){ System.out.println("許可權校驗================"); } return method.invoke(userDao, args); } }

Cglib 的動態代理(實現MethodInterceptor)

  • 針對沒有實現介面的類產生代理. 應用的是底層的位元組碼增強的技術 生成當前類的子類物件
package springpro1;

import java.lang.reflect.Method;

import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;

//CGLIB代理類

public class LogCglibProxy implements MethodInterceptor{
	private Object target; // 代理的目標物件
	
	/**
	 * 建立代理物件
	 * @param <T>
	 * @param target 目標物件
	 */
	@SuppressWarnings("unchecked")
	public <T> T createProxyInstance(T target) {
		this.target = target;
		Enhancer enhancer = new Enhancer(); // 該類用於生成代理物件
		enhancer.setSuperclass(target.getClass()); // 設定父類
		enhancer.setCallback(this); // 設定回撥物件為自己這個物件
		return (T) enhancer.create(); // 建立代理物件並返回
	}
	
	/**
	 * @param proxy 		 目標物件代理類的例項
	 * @param method		代理類例項上呼叫父類方法的Method例項
	 * @param args 			傳入到方法引數值的物件陣列
	 * @param methodProxy 	使用它呼叫父類的方法
	 */
	@Override
	public Object intercept(Object proxy, Method method, Object[] args,MethodProxy methodProxy)	throws Throwable {
		System.out.println(proxy.getClass());
		System.out.println("== Log:開始執行操作,方法名:" + method.getName() + " ==");
		Object result = methodProxy.invoke(target, args); // 執行原方法
		System.out.println("== Log:操作執行完畢 ==");
		return result;
	}
	
}

測試

package springpro1;

import com.test.dao.UserDao;
import com.test.dao.impl.UserDaolmpl;

public class TestDemo2 {
	public static void main(String[] args) {
		UserDao ud = new UserDaolmpl();
		 
		new MyJDKProxy(ud).createProxy().save();
		
		System.out.println("--------------------------------------------");
		
		new LogCglibProxy().createProxyInstance(ud).save();
	}
}

在這裡插入圖片描述