一. 为什么要有代理模式
中金隔离作用 : 在某些情况下,一个客户不想或者不能直接引用一个委托对象,而代理对象可以在客户类和委托对象之间起到中介作用,主要特征是代理类和委托类实现相同接口。
开闭原则,增加功能 : 在除啦作为中介外,还可以在代理类中进行切面性业务修改,如增加日志,缓存等,而主线业务代理类并不处理,都是交给委托类来处理的,也就是调用委托类的方法;
二.静态代理
第一步:创建委托类
package com.yhou.proxy.impl;
import com.yhou.proxy.Subject;
/**
* @author houyong
* @ProjectName Designpattern
* @Description: 委托者(被代理者) 该主题的具体实现,一段业务逻辑
* 实际对象实际的执行者
* @date 2019/03/07 下午5:20
*/
public class RealSubject implements Subject {
private String name = "Leo";
@Override
public void visit() {
System.out.println("My name is " + name);
}
}
第二步:创建委托类接口
package com.yhou.proxy;
/**
* @author houyong
* @ProjectName Designpattern
* @Description: 主题接口 将执行者需要的被代理的方法抽象出来告诉代理者需要 代理这些方法
* @date 2019/03/07 下午5:26
*/
public interface Subject {
void visit();
}
第三步:创建代理类
package com.yhou.proxy.impl;
import com.yhou.proxy.Subject;
/**
* @author houyong
* @ProjectName Designpattern
* @Description: 代理者 通过实现抽象接口来知道执行者有哪些方法需要被代理
* @date 2019/03/07 下午5:30
*/
public class ProxySubject implements Subject {
private Subject subject;
public ProxySubject(Subject subject) {
this.subject = subject;
}
@Override
public void visit() {
//进行主业务执行前置操作
subject.visit();
//进行主业务执行后置操作
}
}
第四步:测试类
package com.yhou.proxy;
import com.yhou.proxy.impl.Dynamicproxy;
import com.yhou.proxy.impl.ProxySubject;
import com.yhou.proxy.impl.RealSubject;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
/**
* @author houyong
* @ProjectName Designpattern
* @Description: 静态代理测试类
* @date 2019/03/07 下午5:31
*/
public class TestMain {
public static void main(String[] args) throws Exception {
// 静态代理
proxy();
}
/**
* 静态代理测试方法
*/
public static void proxy() {
ProxySubject proxySubject = new ProxySubject(new RealSubject());
proxySubject.visit();
}
}
总结:
1.可以在对原业务不影响的前提下对功能进行拓展(AOP);
2.每一个需要代理的类都需要创建代理类,工作量大,不易管理。当有接口发生改变时代理类也需要修改,不易维护。
三.动态代理
为了解决代理类频繁创建,与接口发生变化时不易维护我们将代理类的创建通过类加载机制动态加载出来
动态代理 JDK Cglib
第一步与第二步与静态代理相同
JDK动态代理
第三步: 创建动态处理器
package com.yhou.proxy.impl;
import com.yhou.proxy.Subject;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
/**
* @author houyong
* @ProjectName Designpattern
* @Description:
* @date 2019/03/07 下午6:11
*/
public class DynamicproxyHandler implements InvocationHandler {
private Object object;
public DynamicproxyHandler(final Subject subject) {
this.object = subject;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("进行主业务执行前置操作");
Object invoke = method.invoke(object, args);
System.out.println("进行主业务执行后置操作");
return invoke;
}
}
第四步:编写测试类
package com.yhou.proxy;
import com.yhou.proxy.impl.DynamicproxyHandler;
import com.yhou.proxy.impl.ProxySubject;
import com.yhou.proxy.impl.RealSubject;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
/**
* @author houyong
* @ProjectName Designpattern
* @Description:
* @date 2019/03/07 下午5:31
*/
public class TestMain {
public static void main(String[] args) throws Exception {
// 静态代理
//proxy();
// 动态代理
dynamicClient();
}
public static void proxy() {
ProxySubject proxySubject = new ProxySubject(new RealSubject());
proxySubject.visit();
RealSubject realSubject = new RealSubject();
realSubject.visit();
}
public static void dynamicClient() throws Exception {
DynamicproxyHandler dynamicproxy = new DynamicproxyHandler(new RealSubject());
Class<?> proxyClass = Proxy.getProxyClass(Subject.class.getClassLoader(), new Class[]{Subject.class});
Subject o = (Subject) proxyClass.
getConstructor(new Class[]{InvocationHandler.class}).
newInstance(new Object[]{dynamicproxy});
o.visit();
}
}