代理模式二:Java动态代理

版权声明:如果觉得文章对你有用,转载不需要联系作者,但请注明出处 https://blog.csdn.net/jinxin70/article/details/82949805

Java动态代理

如果你已经了解代理模式,但是不知道Java动态代理的实现,可以阅读本文,必须自己动手写一遍,并运行。但即使这样操作后你的水平也只是用过Java动态代理而已,具体的内部实现,需要debug进源码进行分析。

1、定义一个公共接口Greeting.java:

package aop;

public interface Greeting {

    void sayHello(String name);
}

2、定义真实业务逻辑类GreetingImpl.java,实现Greeting接口,重写sayHello方法:

package aop.demo3;

import aop.Greeting;

public class GreetingImpl implements Greeting {

    public void sayHello(String name) {
        System.out.println("Hello! " + name);
    }
}

3、定义代理类JDKDynamicProxy的逻辑,实现InvocationHandler接口,重写invoke方法,在invoke中添加额外逻辑before()和after(),并调用真实业务方法method.invoke(target,args);

调用Proxy.newProxyInstance方法生成代理类对象,客户端实际使用的是这个对象:

package aop.demo3;

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

public class JDKDynamicProxy implements InvocationHandler {

    private Object target;

    public JDKDynamicProxy(Object target) {
        this.target = target;
    }

    //生成代理对象,传入真实业务类的classloader、真实业务类实现的接口、InvocationHandler 
    @SuppressWarnings("unchecked")
    public <T> T getProxy() {
        return (T) Proxy.newProxyInstance(
            target.getClass().getClassLoader(),
            target.getClass().getInterfaces(),
            this
        );
    }

    //增强真实业务类的调用
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        before();
        Object result = method.invoke(target, args);
        after();
        return result;
    }

    private void before() {
        System.out.println("Before");
    }

    private void after() {
        System.out.println("After");
    }
}

4、客户端使用动态代理,通过构造器注入真实业务类对象,调用getProxy方法获得代理类对象,调用代理方法sayHello:

package aop.demo3;

import aop.Greeting;

/**
 * 3. JDK 动态代理
 */
public class Client {

    public static void main(String[] args) {
        Greeting service = new GreetingImpl();
        Greeting greeting = new JDKDynamicProxy(service).getProxy();
        greeting.sayHello("Jack");
    }
}

5、执行结果:

下一篇,深入Java动态代理原理

一些问题:

Java动态代理只能代理接口,不能代理没有接口的类。(为什么只能代理接口?从Proxy.newProxyInstance可以看出,这个方法是生成代理类对象用的,第二个参数要求传递真实业务类的接口,并且最终生成的代理类和真实业务类实现了同样的接口。更具体的细节,看下一篇Java动态代理原理分析就知道了)

假如我想要增强一个没有接口的类,怎么办呢?CGLib类库可以代理没有接口的类。

参考文章及案例代码:

https://www.jianshu.com/p/a1d094fc6c00  参考了该文章的行文逻辑

https://my.oschina.net/huangyong/blog/161338 参考了代码

猜你喜欢

转载自blog.csdn.net/jinxin70/article/details/82949805
今日推荐