jdk動態代理與cglib程式碼實現--SpringAop底層原理
阿新 • • 發佈:2018-12-10
動態代理分為兩類:基於介面的代理和基於繼承的代理
兩類實現的代表是:JDK代理 與 CGlib代理
cglib實現動態代理:
1、定義目標物件:
public class RealSubject { //目標物件RealSubject,cglib不需要定義目標類的統一介面 public void request() { System.out.println("real subject execute request"); } public void hello() { System.out.println("hello"); } }
2、定義方法攔截器
public class MyMethodInterceptor implements MethodInterceptor { @Override public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { System.out.println("before in cglib"); Object result = null; try{ result = proxy.invokeSuper(obj, args); }catch (Exception e){ System.out.println("get ex:"+e.getMessage()); throw e; }finally { System.out.println("after in cglib"); } return result; } }
3、建立增強後的代理物件
public class Client { public static void main(String[] args){ Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(RealSubject.class); enhancer.setCallback(new MyMethodInterceptor()); // 此刻,realSubject不是單純的目標類,而是增強過的目標類 RealSubject realSubject = (RealSubject) enhancer.create(); realSubject.hello(); realSubject.request(); } }
jdk實現動態代理:
1、想要使用動態代理的目標類實現一個介面
public interface Subject {
void request();
void hello();
}
public class RealSubject implements Subject {
@Override
public void request() {
System.out.println("request");
}
@Override
public void hello() {
System.out.println("hello");
}
}
2、代理物件實現InvocationHandler介面
public class RealSubject implements Subject {
@Override
public void request() {
System.out.println("request");
}
@Override
public void hello() {
System.out.println("hello");
}
}
3、jdk的代理類proxy建立代理物件
public class Forjdk {
public static void main(String[] args){
Subject subject = (Subject) Proxy.newProxyInstance(Forjdk.class.getClassLoader(),new Class[]{Subject.class},new JdkProxySubject(new RealSubject()));
subject.hello();
subject.request();
}
}
SpringAop中的兩種代理方式
若目標物件實現了介面,spring預設使用JDK的動態代理。
優點:因為有介面,所以使系統更加鬆耦合
缺點:為每一個目標類建立介面
若目標物件沒有實現任何介面,spring使用CGLIB進行動態代理。
優點:因為代理類與目標類是繼承關係,所以不需要有介面的存在。
缺點:因為沒有使用介面,所以系統的耦合性沒有使用JDK的動態代理好。
若目標物件實現了介面,但是強制cglib代理,則使用cglib代理