1.定义
给某个对象提供一个代理对象,由代理对象控制对原对象的引用。
区别:
1.适配器模式:适配器模式改变对象的接口,代理模式不改变接口。
2.装饰器模式:装饰者模式是为了增加功能,代理模式是为了控制。
2.使用场景
1.中介隔离:隔离访问,原对象不能被直接引用时,代理对象可以通过实现相同的接口来间接提供给客户访问。
2.功能增强:扩展原对象的功能。主要负责预处理,过滤,事后对返回结果的处理。比如日志功能,解决乱码问题。
3.使用方法
按代理创建的时期,分为静态代理,动态代理。
静态代理是在源码上创建,并对其编译。
动态代理是在程序运行时,通过反射机制动态创建。
注意:代理对象不需要实现接口,但是目标对象一定要实现接口,否则不能用动态代理
3.1 静态代理
1.创建服务接口
public interface Machine {
void run();
}
2.创建原对象
public class RealMachine implements Machine {
private String machineName;
public RealMachine(String machineName){
this.machineName = machineName;
init();
}
@Override
public void run() {
System.out.println("run " + machineName);
}
private void init(){
System.out.println("init "+machineName);
}
}
3.创建代理对象
public class ProxyMachine implements Machine{
private RealMachine realMachine;
private String machineName;
public ProxyMachine(String machineName){
this.machineName = machineName;
}
@Override
public void run() {
if(realMachine == null){
realMachine = new RealMachine(machineName);
}
System.out.println("start run");
realMachine.run();
System.out.println("stop run");
}
}
4.测试
@Test
public void testStaticMachine(){
Machine machine = new ProxyMachine("robot 001");
machine.run();
}
静态代理总结
每一个原对象都要创建一个代理类,不适合
3.2 动态代理
1.创建动态代理类
public class DynamicProxyHandler implements InvocationHandler{
private Object object;
public DynamicProxyHandler(final Object object){
this.object = object;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("start proxy run");
Object invoke = method.invoke(object, args);
System.out.println("stop proxy run");
return invoke;
}
}
2.测试
@Test
public void testDynamicMachine(){
Machine machine = new RealMachine("robot 002");
Machine proxyMachine = (Machine) Proxy.newProxyInstance(
Machine.class.getClassLoader(), new Class[]{Machine.class}, new DynamicProxyHandler(machine));
proxyMachine.run();
}
动态代理总结
代理包:java.lang.reflect.Proxy
JDK动态代理需要使用newProxyInstance方法.
static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces,InvocationHandler h )
三个参数:
1.ClassLoader loader: 指定当前目标对象使用类加载器,获取加载器的方法是固定的
2.Class<?>[] interfaces: 目标对象实现的接口的类型,使用泛型方式确认类型
3.InvocationHandler h 事件处理,执行目标对象的方法时,会触发事件处理器的方法,会把当前执行目标对象的方法作为参数传入
3.3 代理工厂
1.创建代理工厂
public class ProxyFactory {
private Object object;
public ProxyFactory(Object object){
this.object = object;
}
public Object getProxyInstance(){
return Proxy.newProxyInstance(
object.getClass().getClassLoader(),
object.getClass().getInterfaces(),
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("start proxyFactory");
Object invoke = method.invoke(object, args);
System.out.println("stop proxyFactory");
return invoke;
}
}
);
}
}
2.测试
@Test
public void testProxyFactory(){
Machine machine = new RealMachine("robot 003");
Machine proxyInstance = (Machine) new ProxyFactory(machine).getProxyInstance();
proxyInstance.printMessage("test");
}
3.4 cglib代理工厂
和JDK代理不同,当目标对象没有实现任何接口时,cglib代理可以对目标对象进行代理。
cglib代理,又名子类代理。它是在内存中构建一个子类对象,从而实现对目标对象功能的扩展。
1.依赖包
asm-2.2.3,asm-commons-2.2.3,asm-util-2.2.3 ,cglib-nodep-2.1_3
2.创建实体
public class CglibMachine{
private RealMachine realMachine;
private String machineName;
public CglibMachine(){
}
public CglibMachine(String machineName){
this.machineName = machineName;
}
public void run() {
if(realMachine == null){
realMachine = new RealMachine(machineName);
}
System.out.println("start run");
realMachine.run();
System.out.println("stop run");
}
}
3.创建工厂
public class CglibProxyFactory implements MethodInterceptor{
private Object object;
public CglibProxyFactory(Object object){
this.object = object;
}
//给目标对象创建一个代理对象
public Object getProxyInstance(){
//工具类
Enhancer enhancer = new Enhancer();
//设置父类
enhancer.setSuperclass(object.getClass());
//设置回调函数
enhancer.setCallback(this);
//创建子类
return enhancer.create();
}
@Override
public Object intercept(Object target, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
System.out.println("start cglib proxy");
//执行目标对象方法
Object invoke = method.invoke(object, args);
System.out.println("stop cglib proxy");
return invoke;
}
}
4.测试
@Test
public void testCglibFactory(){
CglibMachine machine = new CglibMachine("robot 004");
CglibMachine proxyInstance = (CglibMachine) new CglibProxyFactory(machine).getProxyInstance();
proxyInstance.run();
}