一、代理模式基本概述
代理模式给某一个对象提供一个代理对象,并由代理对象控制对原对象的引用。通俗的来讲代理模式就是我们生活中常见的中介。
二、代理模式的优势
1、解耦
2、功能扩展
三、代理模式的分类
1、静态代理:由程序员创建或由特定工具自动生成源代码,再对其编译。在程序运行前,代理类的.class文件就已经存在了。
2、动态代理:在程序运行时,运用反射机制动态创建而成。
四、静态代理和动态代理的区别
静态代理通常只能代理一个类,而动态代理是代理一个接口下的多个实现类
静态代理实现知道要代理的是什么,而动态代理不知道要代理什么东西,只有在运行的时候才知道
五、静态代理代码案列
package com.sheting.reflect.proxy.staticproxy;
import java.util.Date;
//接口
public interface HelloService {
String echo(String msg);
Date getTime();
}
package com.sheting.reflect.proxy.staticproxy;
import java.util.Date;
//实现类
public class HelloServiceImpl implements HelloService {
@Override
public String echo(String msg) {
return "echo:" + msg;
}
@Override
public Date getTime() {
return new Date();
}
}
package com.sheting.reflect.proxy.staticproxy;
import java.util.Date;
//代理类
public class HelloServiceProxy implements HelloService {
//表示被代理的HelloService 实例
private HelloService helloService;
public HelloServiceProxy(HelloService helloService) {
this.helloService = helloService;
}
public void setHelloServiceProxy(HelloService helloService) {
this.helloService = helloService;
}
@Override
public String echo(String msg) {
//预处理
System.out.println("before calling echo()");
//调用被代理的HelloService 实例的echo()方法
String result = helloService.echo(msg);
//事后处理
System.out.println("after calling echo()");
return result;
}
@Override
public Date getTime() {
//预处理
System.out.println("before calling getTime()");
//调用被代理的HelloService 实例的getTime()方法
Date date = helloService.getTime();
//事后处理
System.out.println("after calling getTime()");
return date;
}
}
六、JDK动态代理案列
/**
* @author: xuWei
* @create: 2019/12/19
* 接口
*/
public interface People {
public void sayHello();
}
/**
* @program: demo
* @author: xuWei
* @create: 2019/12/19
* @description:实现类
*/
public class PeopleImpl implements People {
@Override
public void sayHello() {
System.out.println("chinesse say hello");
}
}
/**
* @program: demo
* @author: xuWei
* @create: 2019/12/19
* @description:代理类
*/
public class PeopleInvocationHandler implements InvocationHandler {
private Object target;
public Object getTarget(Object target) {
this.target = target;
return Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(),this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("记录日志开始");
Object invoke = method.invoke(target, args);
System.out.println("记录日志结束");
return invoke;
}
}
八、Cglib动态代理
/**
* @program: demo
* @author: xuWei
* @create: 2019/12/19
* @description:Cglib动态代理类
*/
public class CglibDynamisProxy implements MethodInterceptor {
private Object target;
public Object getInstance(Object target){
this.target=target;
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(this.target.getClass());
enhancer.setCallback(this);
return enhancer.create();
}
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("记录日志开始");
Object invoke = methodProxy.invokeSuper(o,objects);
System.out.println("记录日志结束");
return invoke;
}
}
九、JDK动态代理和Cglib动态代理的区别?
JDK动态代理利用反射机制实现一个代理接口的匿名类,如果目标对象实现了接口,默认情况下采用JDK代理
Cglib动态代理,将代理对象的class文件加载进来,通过修改字节码生成子类来处理,覆盖其中的方法,因为是继承,所以目标对象的类或方法最好不要声明成final
十、JDK为什么不能针对类生成代理?
由于java的单继承,动态生成的代理类已经继承了Proxy类的,就不能再继承其他的类,所以只能靠实现被代理类的接口的形式,故JDK的动态代理必须有接口。