Java中的动态代理

Java中的动态代理
关于代理Proxy 常用的有三种
静态代理 jdk动态代理 (接口代理) cglib动态代理

静态代理
代理类和实现类 都实现同样的接口 然后代理类中一个属性用来保存实现类 并通过构造函数或者set方法注入实现类对象
然后调用代理类的方法
这样就能做到在调用实现类方法之前 先调用代理类的逻辑

静态代理的demo
package Proxy;

public interface Animal {

public void sayHello(String catname);

}

实现类
package Proxy;

public class Cat implements Animal{
@Override
public void sayHello(String catname) {
System.out.println("猫主子("+catname+")😒#@$%$%^&*%$%");
}
}

代理类
package Proxy;

public class CatProxy implements Animal {

private Animal cat = new Cat();
@Override
public void sayHello(String catname) {
System.out.println("铲屎官:下面有请猫主子("+catname+")发话");
cat.sayHello(catname);
System.out.println("铲屎官:猫主子("+catname+")说了,这些小鱼干都是我的");
}

public static void main(String[] args) {
//创建代理对象 调用方法
CatProxy catProxy = new CatProxy();
catProxy.sayHello("哈哈");
}
}

效果

jdk动态代理(接口代理)

为什么叫动态代理?
静态代理所有的方法都硬编码写死了 不灵活

动态代理不需要自己实现代理类 但是实现类必须实现接口
而是jdk在运行时自动生成代理类对象 传入需要增强的逻辑代码

jdk的代理类 java.lang.reflect.Proxy
jdk实现代理只需要使用newProxyInstance()方法
static Object newProxyInstance(ClassLoader loader, Class[] interfaces,InvocationHandler h ) 参数依次为 ClassLoader loader,: 指定当前目标对象使用类加载器,获取加载器的方法是固定的 Class[] interfaces,: 目标对象实现的接口的类型,使用泛型方式确认类型
InvocationHandler h: 事件处理,使用代理对象执行目标对象的方法时,会触发事件处理器

例子

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class CatProxy {

public static void main(String[] args) {

//目标对象
Animal cat = new Cat();
//生成对应的代理对象
Animal animal = (Animal) Proxy.newProxyInstance(
//类加载器
CatProxy.class.getClassLoader(),
//目标对象实现的接口
cat.getClass().getInterfaces(),
//事件处理程序
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//args表示调用方法传入的参数
String catname = (String) args[0];
System.out.println("铲屎官:下面有请猫主子("+catname+")发话");
//proxy代理对象
//System.out.println(proxy);//这样会报空指针
//因为这个对象是代理对象 是运行时期动态生成的
System.out.println(proxy.getClass());
//方法对象(反射中一样)
//返回 调用方法的结果 传入目标对象和参数
method.invoke(cat,args);

System.out.println("铲屎官:猫主子("+catname+")说了,这些小鱼干都是我的");
return null;

}
}
);

// System.out.println(animal.getClass());
//调用代理对象
animal.sayHello("嘻嘻");
}
}

但是这样



都是没问题的

CGLIB子类代理

jdk接口代理 class $Proxy implement Animal

如果被代理对象没有实现接口 如何对对象方法进行扩展呢?
可以使用子类代理 CGLIB
class $CGLIB12345 extends Cat

在内存中构建一个目标类的子类 从而实现对目标类功能的扩展

Cglib是一个高性能的代码生成包

所以需要依赖 用spring的就可以了

    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-core</artifactId>
        <version>5.0.2.RELEASE</version>
    </dependency>

例子

实体类
package cglib;

public class Cat{
public void sayHello(String catname) {
System.out.println("猫主子("+catname+")😒#@$%$%^&*%$%");
}
}

测试
package cglib;

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 Test {
public static void main(String[] args) {
//目标对象
Cat cat = new Cat();
//对目标类创建cglib代理对象
Cat catproxy = (Cat)Enhancer.create(
Cat.class,
new MethodInterceptor() {
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
//获取方法名
String name = method.getName();
//获取参数
String catname = (String) objects[0];
//调用方法
System.out.println("铲屎官:下面有请猫主子("+catname+")发话");
method.invoke(cat,catname);
System.out.println("铲屎官:猫主子("+catname+")说了,这些小鱼干都是我的");
return null;
}
}
);
System.out.println(catproxy.getClass());
catproxy.sayHello("哈哈");
}
}

posted @ 2019-09-09 11:17  Tamako666  阅读(95)  评论(0编辑  收藏  举报