Java框架學習_Spring(三)Spring_AOP底層實現:JDK動態代理和Cglib動態代理
阿新 • • 發佈:2019-01-10
AOP和IOC是Spring的兩大思想,AOP即面向切面程式設計,和OOP相輔相成,具體請看: AOP(面向切面程式設計)
這裡學習一下它的底層實現方法----動態代理,動態代理關鍵的是代理,就像你去公司辦事,你有什麼需求,不可能直接找到 boss(原始碼),而是通過祕書(代理)來實現你的需求,Boss辦事也是通過代理實現的,(java中很多的思想就是解耦和,將原始碼和業務實現分開,儘量不要去動原始碼,方便程式碼複用和管理)
1、JDK動態代理: 只能對實現了介面的類(或者直接對這個介面)進行代理
這一點很重要,如果JDK要對一個類進行動態代理,那麼這個類必須是實現了一個介面,比如UserDaoImpl implement UserDao,這個時候才能對UserDaoImpl或者直接對UserDao進行代理
具體代理方法如下:
package cn.nupt.demo01.UserDao;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
//建立代理類
public class ProxyTest implements InvocationHandler {
private UserDao userDao;
// 建構函式,傳入我要代理的類,初始化代理類
public ProxyTest(UserDao userDaoTrue) {
this.userDao = userDaoTrue;
}
// 建立代理類的例項:userDao.getClass().getInterfaces()就是獲得這個介面實現的所有介面
public UserDao createProxy() {
// 返回的是Object,強轉到介面或實現類
// 引數1:類載入器; 引數2:所有實現的介面集合;引數三:實現了InvocationHandler的類,在這裡就是本身
UserDao userDaoProxy = (UserDao) Proxy.newProxyInstance(userDao.getClass().getClassLoader (),
userDao.getClass().getInterfaces(), this);
return userDaoProxy;
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if ("save".equals(method.getName())) {
// 需要增強的方法
System.out.println("加入動態代理實現");
// 通過反射返回這個方法的實現
return method.invoke(userDao, args);
}
return method.invoke(userDao, args);
}
}
建立測試類:
@Test
public void test04() {
UserDao daoImpl = new UserDaoImpl();
UserDao proxy = new ProxyTest(daoImpl).createProxy();
proxy.save();
proxy.delete();
}
輸出:
儲存使用者
加入動態代理實現
刪除使用者
2、Cglib動態代理: 可以直接對類代理
Cglib是第三方類庫,需要導包,這裡只需要將Spring的核心包匯入就行了(見前面Spring配置)
具體代理方法如下:
import java.lang.reflect.Method;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
public class ProxyDemo implements MethodInterceptor {
private Coustomer coustomer;
public ProxyDemo(Coustomer coustomer) {
this.coustomer = coustomer;
}
public Coustomer createProxy() {
// 1、建立cglib的核心類物件
Enhancer enhancer = new Enhancer();
// 2、設定父類
enhancer.setSuperclass(coustomer.getClass());
// 3、設定回撥(相當於InvocationHandler)
enhancer.setCallback(this);
// 4、建立代理物件並返回
Coustomer proxy = (Coustomer) enhancer.create();
return proxy;
}
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
if ("hehe".equals(method.getName())) {
System.out.println("增強了");
return methodProxy.invokeSuper(proxy, args);
}
return methodProxy.invokeSuper(proxy, args);
}
}
測試類:
@Test
public void test() {
Coustomer coustomer = new Coustomer();
Coustomer proxy = new ProxyDemo(coustomer).createProxy();
proxy.haha();
proxy.hehe();
}
輸出:
haha
增強了
hehe