动态代理简单来说,就是在你需要用到某个类的时候,由Proxy给你动态构建这个类,同时你可以根据自己的需求定制具体方法的实现。
它可以在运行时动态实现接口,不仅可以有效解耦,还能实现很多操作,比如混淆编译,即编译的时候在代码中混淆一些东西,防止别人反编译,;另一个就是方法拦截器,这个可操作性也很大,比如AOP、日志记录等。
由于本次主要记录一下在RPC中使用jdk动态代理,所以这里简单介绍一下。
public interface ProxyService {
void proxyMethod();
}
public class ProxyServiceImpl implements ProxyService {
@Override
public void proxyMethod() {
System.out.println("ProxyService.proxyMethod() running");
}
public class MyInvocationHandler implements InvocationHandler {
private Object target;
public MyInvocationHandler(Object target){
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
System.out.println("MyInvocationHandler.invoke 方法开始");
method.invoke(target, args);
System.out.println("MyInvocationHandler.invoke 方法结束");
return null;
}
}
public class JavaProxyTest {
public static void main(String[] args) {
MyInvocationHandler handler = new MyInvocationHandler(new ProxyServiceImpl()); //被代理的对象
ProxyService proxyService = (ProxyService) Proxy.newProxyInstance(JavaProxyTest.class.getClassLoader(), new Class[] { ProxyService.class }, handler);//代理对象
proxyService.proxyMethod();
}
}
在RPC中,由于消费者和服务者在不同的服务器中,所以方法的执行是中服务端中进行的,在发送端的代理方法中,我们发送方法名、接口名、参数类型、具体的参数,在服务端中收到这些参数再执行具体的方法。
public interface HelloService {
String hello(Hello hello);
}
HelloService helloServiceProxy = rpcClientProxy.getProxy(HelloService.class);//代理对象
String sendData = helloServiceProxy.hello(new Hello("111", "send data"));
System.out.println(sendData);
public Object invoke(Object o, Method method, Object[] args) throws Throwable {
log.info("invoked method {}",method.getName());
RpcRequest rpcRequest = RpcRequest.builder().methodName(method.getName())
.parameters(args)
.interfaceName(method.getDeclaringClass().getName())
.paramTypes(method.getParameterTypes())
.requestId(UUID.randomUUID().toString())
.build();
//send
sendRpcRequest(rpcRequest);
return "send successful";
}
@Slf4j
public class HelloServiceImpl2 implements HelloService {
static {
System.out.println("HelloServiceImpl2被创建");
}
@Override
public String hello(Hello hello) {
log.info("HelloServiceImpl2收到: {}.", hello.getMessage());
String result = "Hello description is " + hello.getDescription();
log.info("HelloServiceImpl2返回: {}.", result);
return result;
}
}
HelloService helloServiceImpl2 = new HelloServiceImpl2();
RpcServiceConfig rpcServiceConfig = RpcServiceConfig.builder().group("test").version("version2").service(helloServiceImpl2).build();
nettyServer.registerService(rpcServiceConfig);
public Object invokeTargetMethod(RpcRequest rpcRequest) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
String rpcServiceName = rpcRequest.getRpcServiceName();
Object service = serviceProvider.getService(rpcServiceName);//获得实际对象
Method method = service.getClass().getMethod(rpcRequest.getMethodName(), rpcRequest.getParamTypes());
Object invoke = method.invoke(service, rpcRequest.getParameters());
return invoke;
}