代理模式
1:代理模式定义
为其他对象提供一种代理以控制对这个对象的访问,代理对象起到了中介作用,可去掉功能服务或者增加额外的服务。
2:静态代理 Static Proxy
1)继承 extends
子类继承父类,重写其相应方法,增加额外服务,实现代理功能
2)聚合 implements
与被代理的类共同实现同一个接口,在代理类Proxy内部创建被代理类的对象,在被代理类对象调用相应方法的同时,增加额外的服务,实现代理功能。
interface Moveable
Class Car implements Moveable
Class TimeProxy implements Moveable{
Moveable moveable;
创建含参moveable的构造方法,体现面向接口编程的思想
在方法主体中添加代理功能和Moveable的主体方法
}
聚合比继承更适合代理模式,在代理类Proxy的内部使用面向接口编程,并没有指明具体的实现类,而且可以创建多个不同代理功能的代理类,例如日志代理,时间代理,在main方法中把他们联系起来便好,还可以在main方法中决定代理类的使用顺序。
3:动态代理
1)JDK动态代理
1] 创建一个实现接口InvocationHandler的类,它必须实现Invoke方法
2]创建被代理的类以及接口
3]调用Proxy的静态方法,创建一个代理类
newProxyInstance(ClassLoader loader,Class[] interfaces,InvocationHandler h)
4]通过代理调用方法
所谓代理,就是为了修改被代理对象的某些功能,日志代理,时间代理,就是添加了日志功能和时间功能,无谓继承还是聚合,静态代理同时对具体的被代理类进行功能上的修改。动态代理,顾名思义,是动态生成代理类的模式,重点在于把功能和代理区分开来。
TimeHandler就是时间控制器,重写了InvocationHandler类实现了Invoke方法,它不再是某种具体代理类的功能,不再是CarTimeProxy,Time是功能,Proxy是代理。
newProxyInstance()的参数invaocationHandler h 便是为代理类添加功能,至于前面的类加载器和接口,是为了生成具体的代理类,当代理和功能区分开来,便实现了解耦的目的。
Dynamic Proxy是一种Class ,是运行时生成的class,需要实现一组interface。使用动态代理是,必须实现InvocationHandler接口。
2)cglib动态代理
cglib动态代理是针对类实现代理的,对指定目标类产生一个子类,通过方法拦截技术拦截所有父类方法的调用。
JDK动态代理实现invocationHandler,cglib实现MethodIntercepter。
JDK是向上找接口,用接口的抽象方法来替代未知的多种的具体被代理的方法,在此时添加功能。
cglig是在父类方法调用的同时添加功能,运用了拦截器,是向下找子类。
二者相同之处在于,具体的功能都与代理分离,功能都必须重写相应接口的抽象方法,JDK找接口很容易找到,但cglib必须指定给父类,也就是被代理的类。
Enhancer负责设置创建子类的类,即代理类,建议写在MethodIntercepter接口的实现类中。
综上:反射是Java中很重要的思想。
JDK:
//Handler这个就是时间功能
package com.zhao.dynamic_proxy.jdk;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class TimeHandler implements InvocationHandler {
private Object object;
public TimeHandler(Object object) {
super();
this.object = object;
}
/*
* 参数:
* proxy:被代理的对象
* method:被代理对象的方法
* args:方法的参数
*
* 返回值:
* Object:方法的返回值
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// TODO Auto-generated method stub
long startTime = System.currentTimeMillis();
System.out.println("汽车开始行驶~~~");
method.invoke(object);
long endTime = System.currentTimeMillis();
System.out.println("汽车结束行使~~~");
System.out.println("汽车的行驶时间是:" + (endTime - startTime) + "毫秒");
return null;
}
}
//创建代理
package com.zhao.dynamic_proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import org.junit.Test;
import com.zhao.dynamic_proxy.jdk.TimeHandler;
import com.zhao.static_proxy.service.Moveable;
import com.zhao.static_proxy.service.impl.Car;
/*
* JDK动态代理测试类
* */
public class TestJDK {
@Test
public void test() {
Car car=new Car();
InvocationHandler h=new TimeHandler(car);
Class<?> cls=car.getClass();
/*
* loader:类加载器
* interfaces:实现接口
* h:InvocationHandler
* */
Moveable moveable=(Moveable)Proxy.newProxyInstance(cls.getClassLoader(), cls.getInterfaces(), h);
moveable.move();
}
}
Cglib:
package com.zhao.dynamic_proxy.cglib;
import java.lang.reflect.Method;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
public class CglibProxy implements MethodInterceptor{
private Enhancer enhancer=new Enhancer();
public Object getProxy(Class clazz){
//设置创建子类的类
enhancer.setSuperclass(clazz);
enhancer.setCallback(this);
return enhancer.create();
}
/*
* 拦截所有目标类方法的调用
* object:目标类的实例
* method:目标方法的反射对象
* args:方法的参数
* proxy:代理类的实例
* */
@Override
public Object intercept(Object object, Method method, Object[] args, MethodProxy proxy) throws Throwable {
// 代理类调用父类的方法
System.out.println("日志开始~~~~~~~~");
proxy.invokeSuper(object, args);
System.out.println("日志结束~~~~~~~~");
return null;
}
}
//获取代理类(代理类在上面的方法中创建)
package com.zhao.dynamic_proxy;
import org.junit.Test;
import com.zhao.dynamic_proxy.cglib.CglibProxy;
import com.zhao.dynamic_proxy.cglib.Train;
public class TestCglib {
@Test
public void test() {
CglibProxy cglibProxy=new CglibProxy();
Train train=(Train) cglibProxy.getProxy(Train.class);
train.move();
}
}