java动态代理的简单使用

JAVA动态代理的简单使用

一、为啥不用静态代理?

1、静态代理需要实现生成class文件。

2、静态代理需要实现被代理者的所有方法。
例子:假设被代理类有n个方法需要代理类增强功能,即使增强的功能相同,代理类也需要实现这n个方法。

3、一个静态代理类只能代理一个接口。
例子:假设有n个被代理接口都需要增强相同的功能,那么需要n个静态代理。

//需要代理两个方法,代码重复
public class StaticAnimalProxy implements Animal{
    private Animal animal;

    @Override
    public void say(){
        System.out.println("before");
        animal.say();
        System.out.println("after");
    }

    @Override
    public void eat() {
        System.out.println("before");
        animal.eat();
        System.out.println("after");
    }

    public StaticAnimalProxy(Animal animal){
        this.animal = animal;
    }
}
二、JDK原生动态代理
  1. 通过InvocationHandler的invoke方法来回调被代理类的方法。根据给定的类加载器,接口名通过Proxy的newProxyInstance来生成代理实例。
  2. jdk动态代理是通过java反射动态生成代理类的,生成的代理类为Proxy的子类并实现了被代理类的接口。因为是组合关系所有可代理final方法。

对指定方法进行代理

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        if(method.getName().equals("eat")){
            method.invoke(obj,args);
            return null;
        }
        System.out.println("before");
        method.invoke(obj,args);
        System.out.println("after");
        return null;
    }

生成代理对象。

public static Animal getAnProxy(Animal animal){
        DynamicAnimalProxyHandler handler = new DynamicAnimalProxyHandler(animal);
        Animal animalProxy = (Animal) Proxy.newProxyInstance(animal.getClass().getClassLoader(),animal.getClass().getInterfaces(),handler);
        return animalProxy;
    }
三、Cglib动态代理

1、通过使用ASM包,修改被代理类的字节码文件生成一个新的class文件来作为代理类。生成的代理类继承自父类而非接口,因此不能代理final方法。
2、通过MethodInteceptor的intecepter回调父类的方法并增强功能。

被代理类

public class Animal {

    public final void say(){
        System.out.println("happy");
    }

    public void run(){
        System.out.println("run");
    }

    public void sing(){
        System.out.println("sing");
    }
}

MethodInterceptor

public class AnimalMethodInterceptor implements MethodInterceptor {

    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        if(method.getName().equals("sing")){
            return  methodProxy.invokeSuper(o,objects);
        }
        System.out.println("before");
        Object answer = methodProxy.invokeSuper(o,objects);
        System.out.println("after");
        return answer;
    }
}

测试

public class Test {
    public static void main(String[] args){
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(Animal.class);
        enhancer.setCallback(new AnimalMethodInterceptor());
        Animal proxy = (Animal)enhancer.create();
        proxy.run();
        proxy.say();
        proxy.sing();
    }
}
发布了15 篇原创文章 · 获赞 2 · 访问量 439

猜你喜欢

转载自blog.csdn.net/weixin_42379740/article/details/103404034