最近在View时,被问到了静态代理和动态代理二者存在什么区别?说实话,当时是回答的时候是有些懵懵的,一时间竟不知从何说起。于是今天特意研究了下,也分享给屏幕前的你,帮你更好的理解下 静态代理与动态代理。
相信每个人都畅享做一个CEO,梦想可以实现财富自由,走向人生巅峰,那么CEO肯定是只处理重要的事情(也就是决策性的实施),接下来我们就以CEO举例,希望可以加深我们的印象。
定义目标类CEO
分为两步:1、定义ICEO接口;2、实现类Ceo实现接口ICEO
- 定义接口
/**
* @Description 代理接口
* @Author Mr.Gao
* @Date 2024/9/24 23:21
*/
public interface ICEO {
public void meeting();
}
- 实现类
/**
* @Description 实现类
* @Author Mr.Gao
* @Date 2024/9/24 23:22
*/
public class Ceo implements ICEO {
@Override
public void meeting() {
System.out.println("老板需要进行开会...");
}
}
静态代理
通过静态代理方式增强目标类,即就是采用包装类的思想,分为如下几步:1、代理类实现ICEO接口
2、代理类中引入目标类
3、调用目标类的方法,并且在目标类的前后进行增强处理
/**
* @Description 静态代理
* @Author Mr.Gao
* @Date 2024/9/24 23:23
*/
public class CeoStaticProxy implements ICEO {
private ICEO iceo;
public CeoStaticProxy(ICEO iceo) {
this.iceo = iceo;
}
@Override
public void meeting() {
System.out.println("##增强处理(before),先接待客人,然后通知老板开会!");
iceo.meeting();
System.out.println("##增强处理(after),老板开完会了,准备送客~~~");
}
}
- 静态代理单元测试类
/**
* @Description 单元测试静态代理
* @Author Mr.Gao
* @Date 2024/9/24 23:27
*/
public class TestStaticProxy {
public static void main(String[] args) {
// 创建一个包装类
CeoStaticProxy staticProxy = new CeoStaticProxy(new Ceo());
// 开始执行
staticProxy.meeting();
}
}
- 运行结果
根据静态代理引出动态代理
经过静态代理可以发现,确实可以达到代理类的效果,但是会引发一个新的问题,那就是需要为每一个目标对象新建一个代理实现类,这样如果少量的话也还可以接受,但是如果量大的话就会特别麻烦,而且显得代码非常的臃肿,为了解决这个问题,则引入了动态代理的概念。
动态代理
JDK动态代理
/**
* @Description JDK动态代理
* @Author Mr.Gao
* @Date 2024/9/24 23:29
*/
public class JdkProxyFactory {
/**
* JDK动态代理
*
* @param target
* @return
*/
public static Object getProxy(Object target) {
// 保存生成的代理类的字节码文件: jdk8 下的配置,默认生成的路径是项目根目录
System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
return Proxy.newProxyInstance(target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("##增强处理(before),先接待客人,然后通知老板开会!");
// 执行目标方法
Object invoke = method.invoke(target, args);
System.out.println("##增强处理(after),老板开完会了,准备送客~~~");
return invoke;
}
}
);
}
}
- JDK动态代理单元测试类
/**
* @Description 单元测试JDK动态代理
* @Author Mr.Gao
* @Date 2024/9/24 23:34
*/
public class TestJdkProxy {
public static void main(String[] args) {
// 创建目标类
Ceo target = new Ceo();
// 创建目标代理类
ICEO ceoProxy = (ICEO) JdkProxyFactory.getProxy(target);
// 执行目标代理类
ceoProxy.meeting();
}
}
- 运行结果
- 生成JDK代理的Class文件
System.getProperties().put(“sun.misc.ProxyGenerator.saveGeneratedFiles”, “true”); // 会在当前项目下生成$Proxy0文件
Cglib动态代理
/**
* @Description cglib动态代理实现
* @Author Mr.Gao
* @Date 2024/9/24 23:45
*/
public class CglibProxyFactory {
/**
* 创建cglib动态代理类
*
* @param clazz
* @return
*/
public static Object getProxy(Class<?> clazz) {
//指定文件夹生成class文件
System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "D:\\Project\\xbqx\\multi-thread\\");
// 创建动态代理增强类
Enhancer enhancer = new Enhancer();
// 设置类加载器
enhancer.setClassLoader(clazz.getClassLoader());
// 设置被代理类
enhancer.setSuperclass(clazz);
// 设置方法拦截器
enhancer.setCallbacks(new Callback[]{
new MethodInterceptor() {
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("##增强处理(before),先接待客人,然后通知老板开会!");
// 执行目标方法
Object invokeSuper = methodProxy.invokeSuper(o, objects);
System.out.println("##增强处理(after),老板开完会了,准备送客~~~");
return invokeSuper;
}
},
new MethodInterceptor() {
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
Object invokeSuper = methodProxy.invokeSuper(o, objects);
return invokeSuper;
}
}
});
// 对不同方法设置不同的回调逻辑,CallbackFilter中return值为回调数组Callback[]的下标
enhancer.setCallbackFilter(new CallbackFilter() {
@Override
public int accept(Method method) {
//System.out.println("执行方法名称:" + method.getName());
if (method.getName().equals("meeting")) {
return 0;
} else {
return 1;
}
}
});
// 创建代理类
return enhancer.create();
}
}
- Cglib动态代理单元测试类
/**
* @Description cglib动态代理
* @Author Mr.Gao
* @Date 2024/9/24 23:54
*/
public class TestCglibProxy {
public static void main(String[] args) {
// 创建Cglib代理
ICEO ceoProxy = (ICEO) CglibProxyFactory.getProxy(Ceo.class);
// 执行代理方法
ceoProxy.meeting();
}
}
- 运行结果
- 生成Cglib的Class类
JDK动态代理和Cglib动态代理区别
1、JDK动态代理是implements目标类的接口; 而Cglib动态代理是继承目标,作为目标类的子类。
2、JDK动态代理的目标类必须实现接口;而Cglib动态代理的目标类不能被final修饰。
综上所述,是我结合代码层面对静态代理和动态代理的理解,也希望可以帮助到您,加深理解,若存在书写错误的地方,望指正。
今日推荐一言:在日出之际,让我们对世界说早安!