动态代理的两种方式以及区别
Posted 追梦ღ少年᭄ꦿ࿐
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了动态代理的两种方式以及区别相关的知识,希望对你有一定的参考价值。
JDK动态代理
* 基于JDK动态代理
使用前提:
基于JDK动态代理 - 代理类和被代理之间是兄弟级别关系
1.有顶层接口
2.有接口实现类
接口
/**
* 顶层接口
*/
public interface Dog {
public void wang();
public void eat(String food);
public String dance();
}
实现类(切点所在类)
/**
* 接口实现类(被代理类)
*/
public class HaShiQi implements Dog {
public void wang() {
System.out.println("wang...");
}
public void eat(String food) {
System.out.println("吃了" + food + "...");
}
public String dance() {
return "跳舞...";
}
}
测试代码
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* 测试类
*/
public class JDKProxyTest {
public static void main(String[] args) {
//哈士奇是准备被增强对象
final HaShiQi hsq = new HaShiQi();
/**
* 动态代理核心代码
* Proxy.newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
* 参数:
* ClassLoader loader - 使用被代理对象的类加载器
* Class<?>[] interfaces - 使用被代理对象实现的接口数组
* InvocationHandler h - 执行处理器
* 返回值:
*
*/
Dog JiXieHSQ = (Dog) Proxy.newProxyInstance(hsq.getClass().getClassLoader(), hsq.getClass().getInterfaces(), new InvocationHandler() {
/**
* 只要代理对象有任何方法执行,该方法都会运行
* @param proxy 表示最终生成的代理对象
* @param method 表示当前代理对象正在执行的方法
* @param args 表示当前代理对象正在执行的方法的参数
* @return 表示当前代理对象正在执行的方法的返回值
*/
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//针对不同方法进行增强
String methodName = method.getName();
if("wang".equals(methodName)){
//前置增强
System.out.println("机械哈士奇喝了2两...");
//想要实现原有逻辑
Object result = method.invoke(hsq, args);
//后置增强
System.out.println("喝完吐了...");
return result;
}else if("eat".equals(methodName)){
//前置增强
System.out.println("机械哈士奇喝了2两...");
//对于参数进行增强
args[0] = "香肠 + 火腿";
//想要实现原有逻辑
Object result = method.invoke(hsq, args);
//后置增强
System.out.println("打个嗝,睡了...");
return result;
}else if("dance".equals(methodName)){
Object result = method.invoke(hsq, args);
return "唱..." + result + "rap...篮球...";
}else {
//其他方法按照原有逻辑实现
return method.invoke(hsq, args);
}
}
});
//JiXieHSQ.wang();
//JiXieHSQ.eat("香肠");
String result = JiXieHSQ.dance();
System.out.println(result);
}
}
CGlib动态代理
* 基于CGlib动态代理
使用前提:
基于CGlib动态代理 - 代理类和被代理之间是父子级别关系
有父类(继承体系中)
* CGlib动态代理实现步骤
1.需要创建一个增强者对象
2.设置要增强的父类对象
3.设置方法拦截的回调函数
4.获取代理对象,调用方法
父类(切点所在类)
/**
* 顶层父类
*/
public class Cat {
public void miao(){
System.out.println("miao...");
}
}
测试代码
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
public class CGlibProxyTest {
public static void main(String[] args) {
final Cat cat = new Cat();
//1.创建一个增强者对象
Enhancer enhancer = new Enhancer();
//2.设置增强父类对象
enhancer.setSuperclass(cat.getClass());
//3.设置增强回调函数
enhancer.setCallback(new MethodInterceptor() {
/**
* 只要代理对象有任何方法执行,该方法都会运行
* @param proxy 表示最终生成的代理对象
* @param method 表示当前代理对象正在执行的方法
* @param args 表示当前代理对象正在执行的方法的参数
* @return 表示当前代理对象正在执行的方法的返回值
*/
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
/*if("xxx".equals(method.getName())){
args[0] = "猫罐头";
return "吃吃吃吃...";
}*/
System.out.println("喝了2两...");
Object result = method.invoke(cat, args);
System.out.println("吐了...");
return result;
}
});
//4.构建增强对象
Cat pop = (Cat) enhancer.create();
pop.miao();
}
}
以上是关于动态代理的两种方式以及区别的主要内容,如果未能解决你的问题,请参考以下文章
Spring的两种动态代理:Jdk和Cglib 的区别和实现
Spring的两种动态代理:Jdk和Cglib 的区别和实现
java的动态代理的两种方式和spring的aop面向切面编程的对比