java 代理+註解

java 代理+註解

java註解實際上相當於一個標記,可以在使用時通過反射來獲取方法或者類或者屬性上的註解,來實現註解對應的操作。註解一般配合着代理來同時使用,一般使用註解+代理來實現aop。jdk的Proxy只支持接口代理,也就是需要代理的目標類必須有接口,代理類是接口的子類而不是目標類的子類,也就是說對於目標類上的非實現方法無法實現代理。

// 接口類
public interface Test {
    @Count  //jdk的代理獲取註解時,獲取到的是接口方法的註解
    void print();
}
//接口實現類
class TestImpl implements Test{
    public TestImpl() {
    }

    public void print(){
        System.out.println("test");
    }
}

//註解
@Target(METHOD)
@Retention(RUNTIME)
public @interface Count {
    String value() default "";
}

//代理對應的InvocationHandler
class ProxyHandler implements InvocationHandler {

    private Object o;
    private int i=0;
    public Object getProxyInstance(Object object){
        this.o=object;
        return Proxy.newProxyInstance(object.getClass().getClassLoader(),object.getClass().getInterfaces(),this);
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		//這裏實現aop
        if(method.isAnnotationPresent(Count.class)){
            System.out.println("第"+i+"次調用");
        }
        i++;
        return method.invoke(o,args);
    }
}

//測試類
public class ProxyTest {
    public static void main(String[] args) {
        ProxyHandler proxyHandler=new ProxyHandler();
        Object object=proxyHandler.getProxyInstance(new TestImpl());
        System.out.println(object instanceof Proxy);
        System.out.println(object instanceof Test);
        System.out.println(object instanceof TestImpl); //不是目標類的子類
        for (int i = 0; i < 5; i++) {
            ((Test)object).print();
        }
    }
}

測試結果如下:

true
true
false
第0次調用
test
第1次調用
test
第2次調用
test
第3次調用
test
第4次調用
test

spring中的動態代理有兩種實現方式,一種就是如上邊所示使用proxy+InvocationHandler,另外一種使用cglib動態代理,用cglib生成的代理類是目標類的子類,並且不需要接口。實現原理應該與java的類似,都是動態生成代理對象的class字節數組。

參考文檔

1.Spring的兩種代理方式:JDK動態代理和CGLIB動態代理
2.註解Annotation實現原理與自定義註解例子
3.JDK8動態代理源碼分析
4.java動態代理、Proxy與InvocationHandler

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章