代理的意义就在于,在访问真实的数据前我必须先访问它的代理,那么在客户端代码看来代理和实际的类应该没有分别—他们需要是同一类型。要做到是同一类型有两种方式,第一是代理类作为原类的子类,通过继承并重写父类的方法来达到目的;
最好的方式应该是实现同一接口,这就是接口的意义,接口的意义在于抽象,面向接口编程就是面向抽象编程。如果你的类有非static的public的方法,都应该考虑让他实现一个接口,很多时候我们会觉得给一个DAO或者service类多创建个interface是多余的,但是有朝一日你想到给他一个代理这样的需求的时候,你会发现如果他有个接口就完美了。
静态代理实现中,代理类与被代理类必须实现同一个接口。在代理类中可以实现记录等相关服务,并在需要时再呼唤被代理类,这样代理类就可以仅仅保留与业务相关的职责了。
例如:
接口
public interface Ihello {
public void hello(String name);
}
被代理类
public class HelloSpeaker implements Ihello{
@Override
public void hello(String name) {
System.out.println("hello "+name);
}
}
代理类
public class HelloProxy implements Ihello{
private Logger logger=Logger.getLogger(this.getClass().getName());
private Ihello helloObject;
public HelloProxy(Ihello helloObject){
this.helloObject=helloObject;
}
@Override
public void hello(String name) {
log("hello method starts...");
helloObject.hello(name);
log("hello method ends");
}
private void log(String msg) {
logger.log(Level.INFO, msg);
}
}
测试类
public class ProxyDemo {
public static void main(String[] args) {
//静态代理
Ihello proxy=new HelloProxy(new HelloSpeaker());
proxy.hello("Justin");
}
输出:
2017-4-3 9:58:37 javaEE.spring.proxy.serviceImp.HelloProxy log
信息: hello method starts...
hello Justin
2017-4-3 9:58:37 javaEE.spring.proxy.serviceImp.HelloProxy log
信息: hello method ends
可以看到代理类的一个接口只能服务于一种类型的类,而且如果要代理的方法很多,势必要为每个方法进行代理 ,所以静态代理在程序规模稍大时必定无法胜任。
而动态代理不需要为特定类和方法编写特定的代理类,运用jdk1.3以后的可协助开发动态代理功能的API相关类别,使得一个处理者handler可以为各个类服务。
例如:
接口
public interface Ihello {
public void hello(String name);
}
被代理类
public class HelloSpeaker implements Ihello{
@Override
public void hello(String name) {
System.out.println("hello "+name);
}
}
处理类
public class LogHandler implements InvocationHandler {
private Object sub;
public LogHandler(){
}
public LogHandler(Object obj){
sub=obj;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
System.out.println("before you do thing");
method.invoke(sub, args);
System.out.println("after you do thing");
return null;
}
}
测试
public class ProxyDemo {
public static void main(String[] args) {
//动态代理
HelloSpeaker helloSpeaker=new HelloSpeaker();
LogHandler logHandler =new LogHandler(helloSpeaker);
Class cls=helloSpeaker.getClass();
Ihello ihello=(Ihello)Proxy.newProxyInstance(cls.getClassLoader(), cls.getInterfaces(), logHandler);
ihello.hello("Justin");
}
}