jdk動態代理與cglib代碼實現--SpringAop底層原理
動態代理分爲兩類:基於接口的代理和基於繼承的代理
兩類實現的代表是: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代理