代理模式介绍
静态代理没有什么好说的,不断的写新的类,实现与被代理类一样的接口,从而来拓展功能。缺点太多,如接口变化,就要重写新的代理类。
动态代理使用最多的可能就是传说中的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>