Spring底層AOP的原理示例(JDK動態代理和cglib動態代理)
阿新 • • 發佈:2018-12-24
1 JDK動態代理(必須要有介面)
- 介面
package com.itykd.dao;
public interface UserDao {
void save();
void update();
void find();
void delete();
}
- 實現類
package com.itykd.dao.impl; import com.itykd.dao.UserDao; public class UserDaoImpl implements UserDao { @Override public void save() { System.out.println("UserDaoImpl的save方法執行了....."); } @Override public void update() { System.out.println("UserDaoImpl的update方法執行了....."); } @Override public void find() { System.out.println("UserDaoImpl的find方法執行了....."); } @Override public void delete() { System.out.println("UserDaoImpl的delete方法執行了....."); } }
- 提供一個JDK代理類需要繼承InvocationHandler介面,並實現invoke方法,這裡對Dao的save方法進行增強,Proxy的newProxyInstance方法提供三個引數建立UserDao物件,第一個引數是類載入器,第二個引數是介面
package com.itykd.proxy; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import com.itykd.dao.UserDao; public class JDKProxy implements InvocationHandler{ //將被增強的物件傳遞到代理中 private UserDao userDao; public JDKProxy(UserDao userDao) { super(); 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 { //判斷方法是否是save if("save".equals(method.getName())) { //增強 System.out.println("許可權校驗......"); return method.invoke(userDao, args); } return method.invoke(userDao, args); } }
- 測試程式碼
package com.itykd.proxy; import org.junit.Test; import com.itykd.dao.UserDao; import com.itykd.dao.impl.UserDaoImpl; public class ProxyDemo { @Test public void jdkProxyDemo() { UserDao userDao = new UserDaoImpl(); //建立代理 UserDao userDaoProxy = new JDKProxy(userDao).createProxy(); userDaoProxy.save(); userDaoProxy.find(); userDaoProxy.delete(); userDaoProxy.update(); } }
2 Cglib動態代理(繼承的形式生成代理物件)
cglib是第三方開原始碼生成類庫,動態新增類的屬性和方法(原來Hibernate也是用cglib做延遲載入,現在使用的是Javassist技術),Spring的核心包下已經有了Cglib的環境
- 目標類(要增強的類)
package com.itykd.dao;
public class ProductDao {
public void save() {
System.out.println("ProductDao的save方法執行了....");
}
public void update() {
System.out.println("ProductDao的update方法執行了....");
}
public void delete() {
System.out.println("ProductDao的delete方法執行了....");
}
public void find() {
System.out.println("ProductDao的find方法執行了....");
}
}
- cglib代理類
package com.itykd.proxy;
import java.lang.reflect.Method;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
import com.itykd.dao.ProductDao;
public class CglibProxy implements MethodInterceptor{
private ProductDao productDao;
public CglibProxy(ProductDao productDao) {
super();
this.productDao = productDao;
}
public ProductDao createProxy() {
//1 建立cglib的核心類物件
Enhancer enhancer = new Enhancer();
//2 設定父類
enhancer.setSuperclass(productDao.getClass());
//3 設定回撥:(類似於InvocationHandler物件)
enhancer.setCallback(this);
//4 建立代理物件
ProductDao productDaoProxy = (ProductDao)enhancer.create();
return productDaoProxy;
}
@Override
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
//判斷方法是否為save
if("save".equals(method.getName())) {
//增強
System.out.println("許可權校驗...........");
return methodProxy.invokeSuper(proxy, args);
}
return methodProxy.invokeSuper(proxy, args);
}
}
- 測試類
package com.itykd.proxy;
import org.junit.Test;
import com.itykd.dao.ProductDao;
public class ProxyDemo {
public void cglibProxyDemo() {
ProductDao productDao = new ProductDao();
ProductDao productDaoProxy = new CglibProxy(productDao).createProxy();
productDaoProxy.save();
productDaoProxy.find();
productDaoProxy.delete();
productDaoProxy.update();
}
}