正文
如果要想为多个类进行代理,则需要建立多个代理类,维护难度加大。
仔细想想,为什么静态代理会有这些问题,是因为代理在编译期就已经决定,如果代理哪个发生在运行期,这些问题解决起来就比较简单,所以动态代理的存在就很有必要了。
2. 动态代理
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
interface HoseeDynamic
{
String sayhi();
}
class HoseeDynamicimpl implements HoseeDynamic
{
@Override
public String sayhi()
{
return "Welcome oschina hosee's blog";
}
}
class MyProxy implements InvocationHandler
{
Object obj;
public Object bind(Object obj)
{
this.obj = obj;
return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj
.getClass().getInterfaces(), this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable
{
System.out.println("I'm proxy!");
Object res = method.invoke(obj, args);
return res;
}
}
public class DynamicProxy
{
public static void main(String[] args)
{
MyProxy myproxy = new MyProxy();
HoseeDynamicimpl dynamicimpl = new HoseeDynamicimpl();
HoseeDynamic proxy = (HoseeDynamic)myproxy.bind(dynamicimpl);
System.out.println(proxy.sayhi());
}
}
类比静态代理,可以发现,代理类不需要实现原接口了,而是实现InvocationHandler。通过
Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj
.getClass().getInterfaces(), this);
来动态生成一个代理类,该类的类加载器与被代理类相同,实现的接口与被代理类相同。
通过上述方法生成的代理类相当于静态代理中的代理类。
这样就实现了在运行期才决定代理对象是怎么样的,解决了静态代理的弊端。
当动态生成的代理类调用方法时,会触发invoke方法,在invoke方法中可以对被代理类的方法进行增强。
通过动态代理可以很明显的看到它的好处,在使用静态代理时,如果不同接口的某些类想使用代理模式来实现相同的功能,将要实现多个代理类,但在动态代理中,只需要一个代理类就好了。
除了省去了编写代理类的工作量,动态代理实现了可以在原始类和接口还未知的时候,就确定代理类的代理行为,当代理类与原始类脱离直接联系后,就可以很灵活地重用于不同的应用场景中。
2.1 动态代理的弊端
代理类和委托类需要都实现同一个接口。也就是说只有实现了某个接口的类可以使用Java动态代理机制。但是,事实上使用中并不是遇到的所有类都会给你实现一个接口。因此,对于没有实现接口的类,就不能使用该机制。
而CGLIB则可以实现对类的动态代理
2.2 回调函数原理