java反射回顾

jdk动态代理

//动物接口
public interface Animal {
    void shout(String sound);
}
//动物接口实现类
public class Cat implements Animal {
    @Override
    public void shout(String sound) {
        for (int i = 0; i < 3; i++) {
            System.out.print("cat->"+sound + "! ");
        }
        System.out.println();
    }
}
//动物接口实现类
public class Dog implements Animal {
    @Override
    public void shout(String sound) {
        for (int i = 0; i < 3; i++) {
            System.out.print("dog->"+sound + "! ");
        }
        System.out.println();
    }
}

class AnimalProxy implements InvocationHandler {

    private Object target;

    public Object getInstance(Object target) {
        this.target = target;
        return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Object result = null;
        System.out.println("方法调用前...");
        result = method.invoke(target, args);
        System.out.println("方法调用后...");
        return result;
    }

}
public class ProxyTest {
    public static void main(String[] args) {
        AnimalProxy proxy=new AnimalProxy();
        Animal dogProxy= (Animal) proxy.getInstance(new Dog());
        dogProxy.shout("wang");
    }
}

cglib动态代理

JDK动态代理机制缺陷:JDK的动态代理机制只能代理实现了接口的类,而不能实现接口的类就不能实现JDK的动态代理

cglib是针对类来实现代理的,他的原理是对指定的目标类生成一个子类,并覆盖其中方法实现增强,

cglib缺陷 cglib实现动态代理但因为采用的是继承,所以不能对final修饰的类进行代理。

class Snake {
    public void makeSound(String name) {
        System.out.println("Hi," + name + "");
    }
}

class AnimalProxyCglib implements MethodInterceptor {

    private Object target;

    public Object getInstance(Object target) {
        this.target = target;
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(this.target.getClass());
        enhancer.setCallback(this);
        return enhancer.create();
    }

    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        Object result = null;
        System.out.println("方法调用前操作...");
        result = methodProxy.invokeSuper(o, objects);
        System.out.println("方法调用后操作...");
        return result;
    }
}

public class DynamicProxyCglibDemo {
    public static void main(String[] args) {
        AnimalProxyCglib proxy = new AnimalProxyCglib();
        Snake dogProxy=(Snake)proxy.getInstance(new Snake());
        dogProxy.makeSound("tom");
    }
}

RPC利用动态代理调用远程函数

HelloService helloService=rpcProxy.create(HelloService.class);

客户端需要调用远程一个服务对象的时候,通过动态代理的方式创建客户端所需的对象

public  T create(final Class interfaceClass, final String serviceVersion) {
        return (T) Proxy.newProxyInstance(interfaceClass.getClassLoader(), new Class[]{interfaceClass}, new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                //创建RPC请求对象,并设置请求属性
                RpcRequest request = new RpcRequest();
                request.setRequestId(UUID.randomUUID().toString());
                request.setInterfaceName(method.getDeclaringClass().getName());
                request.setMethodName(method.getName());
                request.setParameterTypes(method.getParameterTypes());
                request.setServiceVersion(serviceVersion);
                request.setParameter(args);
                //获取Rpc服务地址
                if (serviceDiscovery != null) {
                    String serviceName = interfaceClass.getName();
                    if (StringUtil.isNotEmpty(serviceVersion)) {
                        serviceName += "-"+serviceVersion;
                    }
                    serviceAddress = serviceDiscovery.discover(serviceName);
                    LOGGER.debug("discover service:{}=>", serviceName, serviceVersion);
                }
                if (StringUtil.isEmpty(serviceAddress)) {
                    throw new RuntimeException("service address is empty ");
                }
                //从rpc服务地址中解析主机名与对应的端口号
                String[] array = StringUtil.split(serviceAddress, ":");
                String host = array[0];
                int port = Integer.parseInt(array[1]);
                //创建rpc客户端对象并且发送rpc请求
                RpcClient client = new RpcClient(host, port);
                long beginTime = System.currentTimeMillis();
                RpcResponse response = client.send(request);
                LOGGER.debug("time:{}ms", System.currentTimeMillis() - beginTime);
                if (response == null) {
                    throw new RuntimeException("response is null ");
                }
                if (response.hasException()) {
                    throw response.getException();
                } else {
                    return response.getResult();
                }
            }
        });
    }

你可能感兴趣的:(java)