每天一个设计模式之代理模式

代理模式介绍

静态代理没有什么好说的,不断的写新的类,实现与被代理类一样的接口,从而来拓展功能。缺点太多,如接口变化,就要重写新的代理类。

动态代理使用最多的可能就是传说中的aop了。它解决了静态代理的缺点,即使接口变化了,代理类也不需要变化。动态代理实现方式主要有两种:1、jdk自带的 2、cglib技术

个人觉得代理模式的用处就是在不对原有类进行修改的情况下,对类的功能进行增强。有前置增强、后置增强、环绕增强、抛出增强、引入增强等。其中前四种增强是对类的方法的增强,叫做织入(Weaving),抛出增强可以对异常进行处理。引入增强是对类进行增强,如给类添加新的方法等。

jdk实现动态代理

接口:

public interface HelloWorld {
  void say();
}

被代理类:

public class Hello implements HelloWorld {

    @Override public void say() {
        System.out.println("Hello World");
    }
}

动态代理类:

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class JdkDynamicProxy {

private static class HelloWorldDynamicProxy implements  
InvocationHandler{

Object target;

public HelloWorldDynamicProxy(Object target) {

this.target = target;
}

@Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("Hello Dota");
method.invoke(target, args);
System.out.println("Hello Dota2");
return null;
}

//Object像下转型为T,会有警告,这里利用了泛型,否则调用完的结果还需要强制转换
@SuppressWarnings("unchecked")
public <T> T getProxy(){
return (T)Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(),this);
}

}

public static void main(String args[]){
Hello hello = new Hello();
HelloWorld proxy = new HelloWorldDynamicProxy(hello).getProxy();
proxy.say();
}
}

结果:

Hello Dota
Hello World
Hello Dota2

Cglib动态代理技术

jdk中的动态代理需要被代理类实现了某个接口。但是cglib可以代理一个没有实现任何接口的类。cglib创建代理的速度比较慢,但是创建代理后运行的速度却非常快,而jdk动态代理却正好相反。还是用上面的例子,cglib的代理类如下。

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;

public class CglibDynamicProxy implements MethodInterceptor {

    private static CglibDynamicProxy cglibDynamicProxy = new CglibDynamicProxy();

    public static CglibDynamicProxy getInstance(){
        return cglibDynamicProxy;
    }

    @SuppressWarnings("unchecked")
    public <T> T getProxy(Class<T> cls){
        return (T) Enhancer.create(cls,this);
    }

    @Override public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println("dota");
        Object object = methodProxy.invokeSuper(o,objects);
        System.out.println("dota2");
        return object;
    }

    public static void main(String args[]){
    CglibDynamicProxy.getInstance().getProxy(Hello.class).say();
    }

}

另外如果工程用maven管理,使用cglib需要添加maven依赖

<dependency>
    <groupId>cglib</groupId>
    <artifactId>cglib</artifactId>
    <version>2.2.2</version>
</dependency>
上一篇:带你读《Python 程序设计与问题求解(原书第2版)》之二:软件开发、数据类型和表达式


下一篇:Spring自定义标签解析