`

jdk动态代理

    博客分类:
  • java
阅读更多
代理模式: 为其他对象提供一种代理,并以控制对这个对象的访问。

代理模式的作用是:为其它对象提供一种代理以控制对这个对象的访问。在某些情况下,一 个客户不想直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介作用。 代理模式一般涉及到三个角色:

抽象角色:声明真实对象和代理对象的共同接口
代理角色:代理对象内部包含有真实角色的引用,从而可以操作真实角色,同时代理对象 与真实对象有相同的接口,能在任何时候代替真实对象,同时代理对象可以在执行真实对 象前后加入特定的逻辑以实现功能的扩展。
真实角色:代理角色所代表的真实对象,是我们最终要引用的对象

代理模式实例:

//抽象角色
public interface Subject {
public void dosomething();
}
//真实角色
public class RealSubject implements Subject {

@Override
public void dosomething() {
System.out.println("do real thing");
}

}
//代理角色
public class ProxySubject implements Subject {
private Subject subject;

public ProxySubject(Subject subject) {
this.subject = subject;
}

@Override
public void dosomething() {
preDoRealThing();

subject.dosomething();

afterDoRealThing();
}

private void preDoRealThing() {
System.out.println("pre do real thing");
}

private void afterDoRealThing() {
System.out.println("after do real thing");
}

public static void main(String[] args) {
Subject realSubject = new RealSubject();
Subject proxySubject = new ProxySubject(realSubject);
proxySubject.dosomething();
}
}


jdk动态代理

jdk动态代理类位于java.lang.reflect包下,一般主要涉及到以下两个类:
Interface InvocationHandler:改接口只定义了一个方法
public Object inveke(Object proxy, Method method, Object[] args)这个抽象方法在代理类中动态实现,proxy一般是指代理类,method代表代理的方法,args代表该方法的参数数组

proxy:动态代理类
protected Proxy(InvocationHandler h):构造函数,估计用于给内部的h赋值。
static Class getProxyClass (ClassLoader loader, Class[] interfaces):获得一个 代理类,其中loader是类装载器,interfaces是真实类所拥有的全部接口的数组。
static Object newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h):返回代理类的一个实例,返回后的代理类可以当作被代理类使用 (可使用被代理类的在Subject接口中声明过的方法)。loader代表代理类的类加载器,interface代表代理类实现的接口,h代表代理类处理器

//抽象角色
public interface Subject {
public void dosomething();
}
//真实角色
public class RealSubject implements Subject {

@Override
public void dosomething() {
System.out.println("do real thing");
}

}
//代理处理器
public class ProxyInvocationHandler implements InvocationHandler {

Object subject;

public ProxyInvocationHandler(Object subject) {
this.subject = subject;
}

@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
System.out.println("before calling:" + method);

method.invoke(subject, args);

System.out.println("after calling:" + method);

return null;
}

}
//代理角色
public class DynamicProxy {
public static void main(String[] args) {
Subject realSubject = new RealSubject();

InvocationHandler invocationHandler = new ProxyInvocationHandler(realSubject);

Subject proxySubject = (Subject)Proxy.newProxyInstance(realSubject.getClass().getClassLoader(), realSubject.getClass().getInterfaces(), invocationHandler);

proxySubject.dosomething();
}

}
   JDK中的动态代理是通过反射类Proxy以及InvocationHandler回调接口实现的。但是,JDK中所要进行动态代理的类必须要实现一个接口,也就是说只能对该类所实现接口中定义的方法进行代理,这在实际编程中具有一定的局限性,而且使用反射的效率也并不是很高。
   使用CGLib实现动态代理,完全不受代理类必须实现接口的限制,而且CGLib底层采用ASM字节码生成框架,使用字节码技术生成代理类,比使用Java反射效率要高。唯一需要注意的是,CGLib不能对声明为final的方法进行代理,因为CGLib原理是动态生成被代理类的子类。

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics