欢迎来到某某机械轴承科技有限公司官方网站!

轴承实业,传动精彩 转动未来

专注轴承定制、生产一站式服务商

咨询热线:

087-500821209 186-0000-0000

某某机械轴承科技有限公司

新闻资讯

新闻资讯

联系我们

手机:186-0000-0000

电话:087-500821209

地址:内蒙古自治区乌海市八宿县建筑大楼298号

常见问题

架构师内功心法,干过中介干过快递的署理模式详解

  • 作者:乐鱼体育app在线登录
  • 发布时间:2021-11-23 20:14
  • 点击:
本文摘要:一、署理模式的应用场景在我们的生活中,经常会见到这样的场景,如:租售房中介、婚介、经纪人、快递等,这些都是署理模式的现实生活体现。署理模式(Proxy Pattern)是指为其它工具提供一种署理,以控制对这个工具的会见。署理工具在客户端和目的工具中间起到了中介的作用,使用署理模式主要有两个目的:一是掩护目的工具,二是增强目的工具。

乐鱼体育app在线登录

一、署理模式的应用场景在我们的生活中,经常会见到这样的场景,如:租售房中介、婚介、经纪人、快递等,这些都是署理模式的现实生活体现。署理模式(Proxy Pattern)是指为其它工具提供一种署理,以控制对这个工具的会见。署理工具在客户端和目的工具中间起到了中介的作用,使用署理模式主要有两个目的:一是掩护目的工具,二是增强目的工具。租售房中介快递场景婚介所署理模式的类图结构:Subject是顶层设计的接口,RealSubject是真实的工具,Proxy是署理工具,署理工具持有真实工具的引用,客户端Client挪用署理工具的方法,同时也挪用真实工具的方法,在署理工具前后增加一些处置惩罚。

我们一想到署理模式,就会明白为代码增强,其实就是在原本的代码逻辑前后增加一些逻辑,而使得挪用者无感知。署理模式分为静态署理和动态署理。

二、署理模式的分类2.1 静态署理我们直接来举例说明静态署理,青年男女到了适婚的年事,如果没有工具,周围的亲戚朋侪总是张罗着要给某某某先容工具,这个先容工具相亲的历程,就是一种我们人人都有份的署理。来看代码实现:顶层接口设计Person类:public interface Person { /** * 寻找朋友 */ void lookForMate();}女儿要求找工具,实现Person接口:public class Daughter implements Person { @Override public void lookForMate() { System.out.println("女儿要求:高峻英俊且有钱!"); }}母亲要帮闺女相亲,实现Mother类:public class Mother { private Daughter daughter; //如何扩展呢 public Mother(Daughter daughter) { this.daughter = daughter; } //目的工具的引用daughter拿到,可以挪用 public void lookForMate() { System.out.println("母亲物色女儿的工具"); daughter.lookForMate(); System.out.println("双方同意来往并确立关系"); } }测试内容:public static void main(String[] args) { //只能帮女儿找工具,不能帮表妹、不能帮生疏人 Mother mother = new Mother(new Daughter()); mother.lookForMate();}运行效果:上面的这个例子是生活中的例子,我们用代码实现了生活中的署理模式。再来一个详细的实际业务场景的例子吧。我们经常会对数据库举行分库分表,分库分表后用Java代码来操作,就需要设置多个数据源,通过设置数据源路由来动态动态切换数据源。

建立订单实体类:/** * 订单实体类 */public class Order { private String id; private Object orderInfo; private Long createTime; public String getId() { return id; } public void setId(String id) { this.id = id; } public Object getOrderInfo() { return orderInfo; } public void setOrderInfo(Object orderInfo) { this.orderInfo = orderInfo; } public Long getCreateTime() { return createTime; } public void setCreateTime(Long createTime) { this.createTime = createTime; }}建立OrderDao持久层操作类:public class OrderDao { public int insert(Order order) { System.out.println("建立order工具乐成!"); return 1; }}建立 IOrderService 接口:public interface IOrderService { int createOrder(Order order);}建立 OrderService 实现类:public class OrderService implements IOrderService { private OrderDao orderDao; public OrderService(OrderDao orderDao) { orderDao = new OrderDao(); } @Override public int createOrder(Order order) { System.out.println("OrderService挪用OrderDao建立订单"); return orderDao.insert(order); }}我们来使用静态署理,完成订单建立时间自动按年份举行分库,通过使用署理工具来完成接下来的代码。建立数据源路由工具,使用ThreadLocal单例实现,DynamicDataSourceEntity:public class DynamicDataSourceEntity { /** * 默认数据源 */ public static final String DEFAULT_DATA_SOURCE = null; private static final ThreadLocal<String> local = new ThreadLocal<>(); private DynamicDataSourceEntity() {} /** * 获取当前正在使用的数据源 * @return */ public static String get() { return local.get(); } /** * 设置已知名字的数据源 * @param dataSource */ public static void set(String dataSource) { local.set(dataSource); } /** * 还原当前切面的数据源 */ public static void restore() { local.set(DEFAULT_DATA_SOURCE); } /** * 凭据年份动态设置数据源 * @param year */ public static void set(int year) { local.set("DB_" + year); } /** * 清空数据源 */ public static void remove() { local.remove(); }}建立切换数据源署理OrderServiceStaticProxy:public class OrderServiceStaticProxy implements IOrderService { private SimpleDateFormat yearFormat = new SimpleDateFormat("yyyy"); private IOrderService orderService; public OrderServiceStaticProxy(IOrderService orderService) { this.orderService = orderService; } @Override public int createOrder(Order order) { before(); Long time = order.getCreateTime(); Integer dbRouter = Integer.valueOf(yearFormat.format(new Date(time))); System.out.println("静态署理类自动分配到【DB_" + dbRouter + "】数据源处置惩罚数据。"); DynamicDataSourceEntity.set(dbRouter); orderService.createOrder(order); after(); return 0; } private void before(){ System.out.println("署理方法执行开始了......"); } private void after(){ System.out.println("署理方法执行竣事了......"); }}main方法的代码:public static void main(String[] args) throws ParseException { Order order = new Order(); order.setId("010101001"); //Date today = new Date(); //order.setCreateTime(today.getTime()); SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd"); Date date = sdf.parse("2019/02/01"); order.setCreateTime(date.getTime()); IOrderService orderService = new OrderServiceStaticProxy(new OrderService()); orderService.createOrder(order);}运行效果是:切合我们的预期效果。现在我们再往返顾一下类图,看是不是和我们最先画的类结构一致:2.2 动态署理动态署理和静态署理的思路基本是一致的,只不外动态署理的功效越发强大,随着业务的扩展适应性更强。

前面说到的母亲替闺女找工具的例子,如果找工具的业务生长为一个行业,那么就是婚姻中介了。来升级代码的实现历程,以满足资助更多的只身人士找工具的需求。下面使用JDK的方式实现婚姻先容所。

2.2.1 JDK实现方式建立婚姻先容JDKMarriage类:public class JDKMarriage implements InvocationHandler { private Object target; public Object getInstance(Object target) { this.target = target; Class<?> clazz = target.getClass(); return Proxy.newProxyInstance(clazz.getClassLoader(), clazz.getInterfaces(), this); } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { before(); Object object = method.invoke(this.target, args); after(); return object; } private void before(){ System.out.println("我是婚姻先容所:要给你找工具,现在已经拿到你的需求"); System.out.println("开始物色"); } private void after(){ System.out.println("如果合适的话,就准备服务"); }}建立只身客户Customer类:public class Customer implements Person { @Override public void lookForMate() { System.out.println("高富帅"); System.out.println("身高180cm"); System.out.println("有房有车"); }}测试main方法代码: public static void main(String[] args) { JDKMarriage marriage = new JDKMarriage(); Person person = (Person) marriage.getInstance(new Customer()); person.lookForMate();}运行效果:上面的动态署理案例通过实现InvocationHandler接口来完成的,在前面的数据源路由业务,也要用动态署理来实现一下,我们来看下代码:public class OrderServiceDynamicProxy implements InvocationHandler { private SimpleDateFormat yearFormat = new SimpleDateFormat("yyyy"); public Object target; public Object getInstance(Object target) { this.target = target; Class<?> clazz = target.getClass(); return Proxy.newProxyInstance(clazz.getClassLoader(), clazz.getInterfaces(), this); } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { before(args[0]); Object object = method.invoke(target, args); after(); return object; } public void before(Object target) { try { System.out.println("署理方法执行开始了......"); Long time = (Long)target.getClass().getMethod("getCreateTime").invoke(target); Integer dbRouter = Integer.valueOf(yearFormat.format(new Date(time))); System.out.println("动态署理类自动分配到【DB_" + dbRouter + "】数据源处置惩罚数据"); DynamicDataSourceEntity.set(dbRouter); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } catch (NoSuchMethodException e) { e.printStackTrace(); } } public void after() { System.out.println("署理方法执行竣事了......"); }}测试main方法代码:public static void main(String[] args) throws ParseException { Order order = new Order(); order.setId("010101001");// Date today = new Date();// order.setCreateTime(today.getTime()); SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd"); Date date = sdf.parse("2019/02/01"); order.setCreateTime(date.getTime()); IOrderService orderService = (IOrderService) new OrderServiceDynamicProxy().getInstance(new OrderService()); orderService.createOrder(order);}运行效果:依然可以到达想要的运行效果。可是,动态署理实现之后,我们不仅能实现 Order 的数据源动态路由,还可以实现其他任何类的数据源路由。2.2.2 CGLib署理挪用API及原理分析pom依赖:<dependency><groupId>cglib</groupId><artifactId>cglib</artifactId><version>3.3.0</version></dependency>还是以婚姻先容所为例,建立CglibMarriage类:public class CglibMarriage implements MethodInterceptor { public Object getInstance(Class<?> clazz) throws Exception { Enhancer enhancer = new Enhancer(); //要把哪个类设置成为生成的新类的父类 enhancer.setSuperclass(clazz); enhancer.setCallback(this); return enhancer.create(); } @Override public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { before(); Object obj = methodProxy.invokeSuper(o, objects); after(); return obj; } private void before(){ System.out.println("我是婚姻先容所:要给你找工具,现在已经拿到你的需求"); System.out.println("开始物色"); } private void after(){ System.out.println("如果合适的话,就准备服务"); }}接着建立只身客户类Customer:public class Customer { public void lookForMate() { System.out.println("高富帅"); System.out.println("身高180cm"); System.out.println("有房有车"); }}注意:CGLib署理的目的工具不需要实现任何接口,它是通过动态继续目的工具实现动态署理的。

来看测试代码:public static void main(String[] args) { try { Customer customer = (Customer)new CglibMarriage().getInstance(Customer.class); customer.lookForMate(); } catch (Exception e) { e.printStackTrace(); }}CGLib署理执行署理工具的方法效率之所以比JDK的高,是因为CGLib接纳了FastClass机制,FastClass的原理是:为署理类和被署理类各生成一个class,这个class会为署理类或被署理类的方法分配一个index(int类型),这个index看成入参,FastClass就可以直接定位要挪用的方法直接举行挪用,这样省去了反射挪用,所以挪用效率比JDK动态署理通过反射挪用高。2.2.3 CGLib和JDK动态署理对比1、JDK动态署理实现了被署理工具的接口,CGLib署理继续了被署理工具。2、JDK和CGLib都在运行期间生成字节码,JDK动态署理直接生成class字节码,CGLib署理通过asm框架生成class字节码,CGLib署理实现更庞大,生成署理类比JDK动态署理效率低。3、JDK动态署理挪用署理方法是通过反射机制挪用的,CGLib署理是通过FastClass机制直接挪用方法的,CGLib署理的执行效率高。

乐鱼体育APP网址

三、Spring与署理模式3.1 署理模式在Spring源码中的应用先看 ProxyFactoryBean 焦点的方法就是 getObject() 方法,我们来看一下源码:@Nullablepublic Object getObject() throws BeansException { this.initializeAdvisorChain(); if (this.isSingleton()) { return this.getSingletonInstance(); } else { if (this.targetName == null) { this.logger.info("Using non-singleton proxies with singleton targets is often undesirable. Enable prototype proxies by setting the 'targetName' property."); } return this.newPrototypeInstance(); }}在 getObject()方法中,主要挪用 getSingletonInstance() 和newPrototypeInstance() ; 在 Spring 的设置中,如果不做任何设置,那么 Spring 署理生成的 Bean 都是单例工具。如果修改 scope则每次建立一个新的原型工具。newPrototypeInstance()内里的逻辑比力庞大,我们后面的课程再做深入研究,这里我们先做简朴的相识。

3.2 Spring 中的署理选择原则Spring 使用动态署理实现 AOP 有两个很是重要的类,一个是 JdkDynamicAopProxy 类和 CglibAopProxy 类,来看一下类图:当 Bean 有实现接口时,Spring 就会用 JDK 的动态署理;当 Bean 没有实现接口时,Spring 选择 CGLib。三、 静态署理和动态的本质区别1、静态署理只能通过手动完成署理操作,如果被署理类增加新的方法,署理类需要同步新增,违背开闭原则。

2、动态署理接纳在运行时动态生成代码的方式,取消了对被署理类的扩展限制,遵循开闭原则。3、若动态署理要对目的类的增强逻辑扩展,联合计谋模式,只需要新增计谋类便可完成,无需修改署理类的代码。四、署理模式的优缺点使用署理模式具有以下几个优点:署理模式能将署理工具与真实被挪用的目的工具分散;一定水平上降低了系统的耦合度,扩展性好;可以起到掩护目的工具的作用;可以对目的工具的功效增强。固然,署理模式也是有缺点的:署理模式会造成系统设计中类的数量增加;在客户端和目的工具增加一个署理工具,会造成请求处置惩罚速度变慢;增加了系统的庞大度。


本文关键词:乐鱼体育APP网址,架构,师,内功,心法,干过,中介,快递,的,署理

本文来源:乐鱼体育APP网址-www.ufotao.com

在线客服
联系方式

热线电话

186-0000-0000

上班时间

周一到周五

公司电话

087-500821209

线