点击上方 "程序员小乐"关注, 星标或置顶一起成长
每天凌晨00点00分, 第一时间与你相约
每日英文
Say to yourself: Regardless of what the obstacles in this life may be, I will run my race to the best of my ability.
对自己说:无论生活之路上会遇到多少障碍,我会竭尽所能地跑完这一程。
每日掏心话
一个丰富的人,内心必须要有一些可以令自己感到荣耀与骄傲的事,它照亮你前方的路。也应有些不安与警觉,它令你不易迷失。只有两者都通晓了,你才能走得稳、走得远。
来自:黑白搬砖工 | 责编:乐乐
链接:juejin.im/post/6844904116888535054
程序员小乐(ID:study_tech)第 982 次推文 图源:百度往日回顾:955 不加班公司名单:955.WLB
正文
1.前言
系统开发已经由单体服务转向为一个一个的微小服务,微小服务的好处就是每个服务只需要关心自己内部的业务,当需要相关业务数据的时候,就会面临服务调用的问题,服务调用其实也好解决,可以使用java自带的HttpURLConnection进行远程服务的调用,也可以使用HttpClient或者是OkHttp这样的第三方客户端进行远程服务调用,同样也可以使用高性能远程调用框架Dubbo。
目前比较流行的微服务技术栈,可以使用基于Netty实现的Dubbo,或者使用基于Http实现的SpringCloud,不管哪种技术,为了实现远程过程调用的便利性,使开发者只需要关注业务本身,而不需要关注调用细节,都采取了反向代理技术。反向代理技术在实现服务间透明调用起到了非常重要作用,既然重要,那么就有必要和大家一起来温习一下反向代理技术。
2.反向代理
2.1 代理的作用
代理的作用就是增强目标方法的能力,比如最常见的事务、Aop都是基于代理来实现的。当需要增强目标方法的能力,并且这些能力都是相同的,那么就可以采取代理的方式进行实现。
2.2 代理的分类
静态代理:静态代理需要为每个被代理的类创建一个代理类,当被代理的类过多的时候,就会导致代理类的增多,不便于维护。
动态代理:动态代理不需要为每个被代理的类创建一个代理类,只需要一个全局的代理类,在需要的时候动态生成,便于维护。
2.3 静态代理
如图可以看到被代理类实现的接口和被代理类其实就是我们开发的业务接口和业务接口实现类,在需要代理的情况下,代理类也要实现被代理类实现的接口,接下来我们来看一下代码的实现。
2.3.1 被代理类实现的接口
public interface HelloService {
void hello();
}
2.3.2 被代理类
public class HelloServiceImpl implements HelloService {
public void hello() {
System.out.println("你吃了嘛?");
}
}
2.3.3 代理类
public class HelloServiceStaticProxy implements HelloService {
private HelloService helloService;
public HelloServiceStaticProxy(HelloService helloService) {
this.helloService = helloService;
}
public void hello() {
System.out.println("你好,我是小王!");
this.helloService.hello();
System.out.println("好的,下次家里聊!");
}
}
2.3.4 测试
@Test
public void staticProxy() {
HelloServiceStaticProxy helloServiceStaticProxy = new HelloServiceStaticProxy(new HelloServiceImpl());
helloServiceStaticProxy.hello();
}
你好,我是小王!
你吃了嘛?
好的,下次家里聊!
2.3.5 小结
静态代理要求代理类和被代理类实现同一个接口,代理对象需要持有被代理的目标对象,在代理对象实现接口方法前后添加增强逻辑并调用目标对象方法。
搜索公众号程序员小乐回复关键字“Java”获取Java面试题和答案。
2.4 动态代理
2.4.1 动态代理实现技术
基于jdk实现
基于Cglib实现
2.4.2 基于jdk实现
2.4.2.1 创建代理类,实现InvocationHandler接口
public class JdkDynamicProxy implements InvocationHandler {
private Object target;
public JdkDynamicProxy(Object target) {
this.target = target;
}
public Object getTarget() {
return target;
}
public void setTarget(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("你好,我是小王!");
Object result = method.invoke(target, args);
System.out.println("好的,下次家里聊!");
return result;
}
}
2.4.2.2 创建代理工厂类
public class JdkDynamicProxyFactory {
private JdkDynamicProxy jdkDynamicProxy;
public JdkDynamicProxyFactory(JdkDynamicProxy helloServiceJdkDynamicProxy) {
this.jdkDynamicProxy = helloServiceJdkDynamicProxy;
}
public Object getProxy() {
Object target = jdkDynamicProxy.getTarget();
return Proxy.newProxyInstance(jdkDynamicProxy.getClass().getClassLoader(), target.getClass().getInterfaces(), jdkDynamicProxy);
}
}
2.4.2.3 测试
@Test
public void test() {
JdkDynamicProxy jdkDynamicProxy = new JdkDynamicProxy(new HelloServiceImpl());
JdkDynamicProxyFactory proxyFactory = new JdkDynamicProxyFactory(jdkDynamicProxy);
HelloService proxy = (HelloService) proxyFactory.getProxy();
proxy.hello();
}
你好,我是小王!
你吃了嘛?
好的,下次家里聊!
2.4.3 基于cglib实现
2.4.3.1 创建代理类,实现MethodInterceptor接口
public class CglibDynamicProxy implements MethodInterceptor {
private Object target;
public CglibDynamicProxy(Object target) {
this.target = target;
}
public Object getTarget() {
return target;
}
public void setTarget(Object target) {
this.target = target;
}
@Override
public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
System.out.println("你好,我是小王!");
Object result = method.invoke(target, args);
System.out.println("好的,下次家里聊!");
return result;
}
}
2.4.3.2 创建代理工厂类
public class CglibDynamicProxyFactory {
private CglibDynamicProxy cglibDynamicProxy;
public CglibDynamicProxyFactory(CglibDynamicProxy cglibDynamicProxy) {
this.cglibDynamicProxy = cglibDynamicProxy;
}
public Object getProxy() {
Enhancer enhancer = new Enhancer();
enhancer.setInterfaces(cglibDynamicProxy.getTarget().getClass().getInterfaces());
enhancer.setCallback(cglibDynamicProxy);
return enhancer.create();
}
}
2.4.3.3 测试
@Test
public void test() {
CglibDynamicProxy cglibDynamicProxy = new CglibDynamicProxy(new HelloServiceImpl());
CglibDynamicProxyFactory proxyFactory = new CglibDynamicProxyFactory(cglibDynamicProxy);
HelloService proxy = (HelloService) proxyFactory.getProxy();
proxy.hello();
}
你好,我是小王!
你吃了嘛?
好的,下次家里聊!
2.4.4 jdk动态代理与cglib动态代理的区别
jdk动态代理不需要引入第三方包,需要实现InvocationHandler接口,要求被代理对象必须实现接口
cglib动态代理需要引入第三方包,需要实现MethodInterceptor接口,被代理对象可以实现接口,也可以不实现接口
3. 总结
今天和大家一起温习了一下代理的相关技术,代理分为:静态代理和动态代理,动态代理的实现技术有:基于jdk来实现和基于cglib来实现,cglib可以针对没有实现接口的目标对象进行代理。
代理技术是后续篇章的讲解的基石,只有掌握代理技术,才能更好的去学习、实现远程过程调用,希望你能牢牢掌握该门技术,可以让自己在后续的篇章中无任何绊脚石。
欢迎在留言区留下你的观点,一起讨论提高。如果今天的文章让你有新的启发,欢迎转发分享给更多人。欢迎加入程序员小乐技术交流群,在后台回复“加群”或者“学习”即可。
猜你还想看
别了,腾讯微博!仅比新浪晚8个月,用户超3亿,马化腾曾亲自宣传,刚刚宣布即将关停
Spring Boot 无侵入式 实现API接口统一JSON格式返回
关注订阅号「程序员小乐」,收看更多精彩内容
嘿,你在看吗?