代理是一种设计模式,提供了对目标对象另外的访问方式,即通过代理对象访问目标对象。可以不修改目标对象,对目标对象功能进行拓展
代理模式的实现分为两大类:静态实现和动态实现,动态实现根据实现的方式分为:jdk 动态实现,cglib动态实现
代理目标接口:定义代理类和目标实现类的基本模板,代理类和目标实现类都要实现这个接口
目标对象: 实现代理目标接口的实现类
代理类: 持有目标对象,根据不同的策略选择不同的方法调用目标对象的方法。
静态代理的优缺点:
优点: 做到不修改目标对象的功能前提下,对目标功能扩展
缺点: 因为代理对象需要与目标对象实现同样的接口,所以会有很多代理类,目标类,同时修改接口,目标类和代理类都要维护。
实现:
代理目标接口:
public interface Person {
void say();
}
实现类:
public class LiudeHua implements Person {
public void say() {
System.out.println("hello,I`m 刘德华");
}
}
实现类2:
public class ZhangSan implements Person {
public void say() {
System.out.println("hello,I`m zhangSan");
}
}
工具类:虽然不是必须的,但是为了体现拓展性,所以还是要:
public class MonitorUtil {
private static ThreadLocal threadLocal = new ThreadLocal();
public static void start(){
System.out.println("开始调用" +System.currentTimeMillis());
threadLocal.set(System.currentTimeMillis());
}
public static void finish(String methodName){
System.out.println("调用结束" +System.currentTimeMillis());
System.out.println(methodName + "方法耗时" + (System.currentTimeMillis() - threadLocal.get()) + "ms");
}
}
代理类:
public class PersonProxy implements Person {
Person liuDeHua = new LiudeHua();
Person zhangSan = new ZhangSan();
public void say() {
}
public void say(String name){
MonitorUtil.start();
if("zhangsan".equals(name)){
zhangSan.say();
}else if("liudehua".equals(name)){
liuDeHua.say();
}
MonitorUtil.finish(name);
}
方法调用:
public static void main(String args[]){
PersonProxy proxy = new PersonProxy();
proxy.say("zhangsan");
proxy.say("liudehua");
}
结果:
Jdk动态代理:
组成部分:
JDK动态代理的优缺点:
优点:动态实现了不改变目标对象逻辑的扩展
缺点:目标必须实现接口,不然无法实现动态代理
Java代码实现:
目标接口:
public interface Person {
void say(String word);
}
实现类:
实现类1:
public class Student implements Person {
public void say(String word) {
System.out.println("我是学生"+word);
System.out.println("我是学生"+word);
System.out.println("我是学生"+word);
}
}
实现类2:
public class Teacher implements Person {
public void say(String word) {
System.out.println(word);
System.out.println(word);
System.out.println(word);
}
}
InvocationHandler接口实现
public class ProxyInvocationHandler implements InvocationHandler {
private Object target;
public ProxyInvocationHandler(Object target){
this.target = target;
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
MonitorUtil.start();
Object resultValue = method.invoke(target,args);
MonitorUtil.finish(target.getClass().getName());
return resultValue;
}
Main类调用:
public class Main {
public static void main(String args []){
Person statudent = new Student();
Person tearcher = new Teacher();
InvocationHandler statudentInvocation = new ProxyInvocationHandler(statudent);
InvocationHandler tearcherInvocation = new ProxyInvocationHandler(tearcher);
Person studentProxy = (Person) Proxy.newProxyInstance(statudent.getClass().getClassLoader(),statudent.getClass().getInterfaces(),statudentInvocation);
Person TearcherProxy = (Person) Proxy.newProxyInstance(tearcher.getClass().getClassLoader(),tearcher.getClass().getInterfaces(),tearcherInvocation);
studentProxy.say("我要好好学习");
TearcherProxy.say("我要带好学生");
}
}
实现结果:
Cglib实现代理
组成部分:
实现类:实现具体目标的逻辑
代理类:实现MethodInterceptor接口,扩展逻辑实现
Enhancer 设置代理类,并且生成代理对象,
优点:
实现了不适用接口就可以实现动态代理
缺点: 实现类没有统一的限定格式
Java代码实现:
目标类:
public class Student {
public void say(){
System.out.println("哈喽");
}
}
代理类:
public class ProxyFactory implements MethodInterceptor {
private Object target;
public ProxyFactory(Object target) {
this.target = target;
}
public Object getInstance(){
Enhancer en = new Enhancer();
en.setSuperclass(target.getClass());
en.setCallback(this);
return en.create();
}
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
MonitorUtil.start();
Object object = method.invoke(target,objects);
MonitorUtil.finish("intercept");
return object;
}
}
启动类:public class Main {
public static void main(String args []) {
Student target = new Student();
Student proxy = (Student) new ProxyFactory(target).getInstance();
proxy.say();
}
}
结果:
三种方法类的思维导图: