动态代理
- 动态代理可以正对一些不特定的
JDK自带的动态代理
- JDK中 java.lang.reflect 包下的Proxy类是Java构造代理类的入口,其中方法newProxyInstance是创建代理对象的方法,方法源码如下:
- 通过Proxy动态代理获得一个代理对象,在代理对象中对某个方法进行增强
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
{}
// ClassLoader loader : 被代理的对的类加载器
// Class<?>[] interfaces:被代理对象所施行的所有接口
// InvocationHandler h:只相信处理器对象,专门用来定义增强的规则
- 在InvocationHandler中是我们实现增强逻辑的地方,其中有一个invoke方法是我们自实现的逻辑
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable;
//Object proxy: 需要代理的对象
//Method method:被代理的方法
//Object[] args:被代理方法运行时的实参
Demo
public interface Person {
public void eat(String name);
public void drink();
}
public class Dog implements Person {
@Override
public void eat(String name) {
System.out.println("dog eat " + name);
}
@Override
public void drink() {
System.out.println("dog drink kele");
}
}
public class MyProxy {
public static void main(String[] args) {
Dog dog = new Dog();
Class[] interfaces = dog.getClass().getInterfaces();
Person proxyPersion = (Person)Proxy.newProxyInstance(dog.getClass().getClassLoader(), interfaces, new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("洗手");
Object obj = method.invoke(dog, args);
System.out.println("洗头");
return obj;
}
});
proxyPersion.eat("面包");
}
}
JDK动态代理总结
-
在不修改原有代码,或者无法修改原有代码的情况下,增强对象功能,使用代理对象代替原来的对象去完成功能而达到扩展功能的目的。
-
JDK动态代理的局限性
-
一定要有接口和实现类的存在
-
增强接口中定义的方法,实现类中其他和接口无关的方法是无法增强的
-
只能读取到接口方法上的注解,不能读取到实现类方法上的注解
-
总而言之,JDK动态代理只能和接口打交道,不能与具体实现类有交集,因为他并不知道所要代理的类是那个实现类
CGLib 动态代理
- demo
/**
* Created by jiamin5 on 2023/3/12.
*/
public class TestCglib {
public static void main(String[] args) {
TestCglib testCglib = new TestCglib();
testCglib.testCglin();
}
public void testCglin(){
//获取一个person的代理对象
Person person = new Person();
//获取一个Enhancer 对象
Enhancer enhancer = new Enhancer();
//设置父类字节码
enhancer.setSuperclass(person.getClass());
//获取MethodInterceptor
MethodInterceptor methodInterceptor = new MethodInterceptor() {
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
// Object obj :生成之后的代理对象personProxy
// Method method:父类中原本要执行的方法 Persion >>> eat()
// Object[] args:方法在调用时候传入的实参数
// MethodProxy proxy:子类中重写父类的方法personProxy >>> eat();
Object res = null;
if(method.getName().equals("eat")){
System.out.println("洗手");
res = proxy.invokeSuper(obj, args);
System.out.println("刷网");
}
return res;
}
};
//设置回调函数:methodInterceptor
enhancer.setCallback(methodInterceptor);
//获得代理对象
Person personProxy = (Person) enhancer.create();
//使用代理对象完成功能
personProxy.eat("面包");
}
static class Person{
public Person(){}
public void eat(String foodName){
System.out.println("eat some 面包 和" + foodName);
}
}
}
-
CGLib 动态代理
- 面向父类的,和接口没有直接关系
- 不仅仅可以增强接口中定义的方法,也可以增强类中的其他方法
-
可以读取父类中方法上所有注解
-
以上Son是由于CGLib生成的一个子类实现,我们在子类中增加了增强逻辑。
版权声明:本文为liaojiamin0102原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。