静态代理
public interface Hello {
public void say();
}
public class HelloImpl implements Hello{
public void say() {
System.out.println("hello");
}
}
现在想在hello前后做些事:使用代理
public class HelloProxy {
private Hello hello;
public HelloProxy(){
hello=new HelloImpl();
}
public void say(){
before();
hello.say();
after();
}
private void after() {
System.out.println("before");
}
private void before() {
System.out.println("after");
}
}
结果:
但是我们不能对每个想要的能力都单独写一个代理,于是就有了动态代理
动态代理
public class DynamicProxy implements InvocationHandler{
private Object target;
public DynamicProxy(Hello hello){
target=hello;
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
before();
Object result=method.invoke(target,args);
after();
return result;
}
private void after() {
System.out.println("before");
}
private void before() {
System.out.println("after");
}
}
DynamicProxy实现了 InvocationHandler, InvocationHandler有一个反射方法invoke()必须实现。
下面是使用方法:
Hello hello=new HelloImpl();
DynamicProxy dynamicProxy=new DynamicProxy(hello);
Hello helloProxy= (Hello) Proxy.newProxyInstance(
hello.getClass().getClassLoader(),
hello.getClass().getInterfaces(),
dynamicProxy);
helloProxy.say();
意思就是通过DynamicProxy去包装了一个HelloImpl的实例,然后调用JDK给我们提供的Proxy的newProxyInstance()方法去动态创建一个Hello接口的代理类
传进去的参数依次为:被代理的类的类加载器,被代理的类的实现接口列表,动态代理对象
通过封装可以更加简洁:
....
public <T> T getProxy(){
return (T) Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(),this);
}
....
Hello hello=new HelloImpl();
DynamicProxy dynamicProxy=new DynamicProxy(hello);
Hello helloProxy=dynamicProxy.getProxy();
helloProxy.say();
但是如果我们需要代理的类没有实现的接口,上面方法就不适用了,为此找到了CGLIB
CGLIB动态代理
这是一个在运行期间动态生成字节码的类,也就是动态生成代理类
public class CGLIBProxy implements MethodInterceptor {
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
before();
Object result=proxy.invokeSuper(obj,args);
after();
return result;
}
public <T> T getProxy(Class<T> cls){
return (T) Enhancer.create(cls,this);
}
private void after() {
System.out.println("before");
}
private void before() {
System.out.println("after");
}
}
其中的Enhancer.create()方法的流程是:
Cglib根据父类,Callback, Filter 及一些相关信息生成key.
然后根据key 生成对应的子类的二进制表现形式
使用ClassLoader装载对应的二进制,生成Class对象,并缓存
最后实例化Class对象,并缓存
再通过下面代码进行调用:
CGLIBProxy cglibProxy=new CGLIBProxy();
Hello helloProxy=cglibProxy.getProxy(HelloImpl.class);
helloProxy.say();
改成单例模式将会更加简单
public class CGLibProxySig implements MethodInterceptor {
private static CGLibProxySig instance=new CGLibProxySig();
private CGLibProxySig(){
}
public static CGLibProxySig getInstance(){
return instance;
}
public <T> T getProxy(Class<T> cls){
return (T) Enhancer.create(cls,this);
}
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
before();
Object result=proxy.invokeSuper(obj,args);
after();
return result;
}
private void after() {
System.out.println("before");
}
private void before() {
System.out.println("after");
}
}