静态代理与动态代理
代理模式
代理模式简单的讲就是代理类帮助委托类完成一些简单任务,而主要功能还是由委托类完成,这样可以使委托类专注于功能的实现,这一些简单任务可以是一些日志,预处理消息等。
静态代理
先创建一个接口,然后创建一个委托类来实现接口并重写方法,再创建一个代理类实现接口,在代理类中创建一个委托类的引用,然后可以调用委托类的方法。
这就是一个很简单的静态代理的过程。
当然,代理类的缺点也是显而易见的,对于一个类的代理当然是十分的简单,当多个类需要代理的时候就会比较麻烦。为了解决这个问题,我们引出了动态代理。
动态代理
动态代理就是在静态代理的基础上为了使代理类自动生成和进行多类代理而衍生出来的。废话不多说,直接用代码解释。
下面展示一些 内联代码片
。
下面展示一些 内联代码片
。
先创建一个接口
HelloInterface.java
package cn.fazi.user;
public interface HelloInterface {
void sayHello();
}
再创建一个委托类
Hello.java
package cn.fazi.user;
public class Hello implements HelloInterface{
@Override
public void sayHello() {
System.out.println("hello sb");
}
}
那么现在重点来了,我们需要写个类来实现InvocationHandler接口,并重写invoke方法。
ProxyHandler.java
package cn.fazi.proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class ProxyHandler implements InvocationHandler{
private Object object;
public ProxyHandler(Object object){
this.object = object;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("Before invoke " + method.getName());
method.invoke(object, args);
System.out.println("After invoke " + method.getName());
return null;
}
}
然后写个测试类来测试一下吧
Test.java
package cn.fazi.proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import cn.fazi.user.Hello;
import cn.fazi.user.HelloInterface;
public class Test {
public static void main(String[] args) {
HelloInterface hello = new Hello();
InvocationHandler handler = new ProxyHandler(hello);
HelloInterface proxyHello = (HelloInterface) Proxy.newProxyInstance(handler.getClass().getClassLoader(),hello.getClass().getInterfaces(),handler);
proxyHello.sayHello();
}
}
运行结果
动态代理的解释
这里就简单的说一下吧。
代理类的创建主要是由 Proxy.newProxyInstance进行创建,通过反射原理进行Proxy的创建,其中InvocationHandler的实现类,主要作用是进行方法的调用,我们从它的名字有可以看出来。
在看源码的过程中,应该有挺多人发现源码中没有对InvocationHandler中的invoke的调用。
这里就解释一下,InvocationHandler中的invoke的调用是在Proxy.newProxyInstance生成代理实例$Proxy后进行的。
HelloInterface proxyHello = (HelloInterface) Proxy.newProxyInstance(handler.getClass().getClassLoader(),hello.getClass().getInterfaces(),handler);
我们从上面实例上来看,代理实例类$Proxy就是proxyHello,而这个类它实际上是继承了Proxy类,通过反射得到被代理类的方法,并对代理类的方法进行重写,在这里重写的方法里面调用了invoke。所以我们调用代理类的方法时,会直接调用invoke。