JAva反射レビュー

10212 ワード

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();
                }
            }
        });
    }