【Java进阶营】Spring IOC的产生背景

在实际项目设计过程中,接口是一个重要组成元素,不同层之间的操作需要通过接口来调用。利用接口,可以实现子类的隐藏,也可以更好地描述不同层之间的操作标准。Java 中要想获得接口对象,需要通过关键字 new 来实现。

【示例 1】通过关键字new实例化接口对象

1.  package demo;
2.  interface  IMessage {    // 定义业务接口
3.  /**
4.  * 信息回显处理
5.  * @param msg 原始信息
6.  * @return 追加回显后的信息
7.  */
8.  public String  echo(String  msg);   
9.  }
10.  class  MessageImpl implements IMessage {    // 定义接口子类
11.  @Override
12.  public String  echo(String  msg) {
13.  return "【ECHO】" + msg;    // 回显处理
14.  }
15.  }
16.  public class  TestMessageDemo {
17.  public static void main(String[] args) {
18.  IMessage  message = new MessageImpl();    // 通过关键字new直接实例化
19.  System.out.println(message.echo("https://mp.weixin.qq.com/mp/profile_ext?action=home&__biz=Mzg3MzczNjYzMA==&scene=124&uin=&key=&devicetype=Windows+10+x64&version=6302019c&lang=zh_CN&a8scene=7&fontgear=2"));
20.  }
21.  }

程序执行后,结果如下:

【ECHO】https://mp.weixin.qq.com/mp/profile_ext?action=home&__biz=Mzg3MzczNjYzMA==&scene=124&uin=&key=&devicetype=Windows+10+x64&version=6302019c&lang=zh_CN&a8scene=7&fontgear=2

本程序是一个典型的 Java 原生代码处理操作。new 是 Java 进行对象实例化最基础的关键字,但使用 new 会暴露 IMessage 接口子类,同时会让子类与接口之间产生耦合,如图 1 所示。

image.png

图 1  通过关键字 new 实例化接口对象

很明显,不同层之间出现接口子类暴露是一种不合理的设计模式,因为调用者并不需要知道具体子类是哪个,只需要取得接口对象即可。采用工厂设计模式,就可以起到解耦合的目的。在此我向大家推荐一个架构学习交流圈。交流学习伪鑫:1253431195(里面有大量的面试题及答案)里面会分享一些资深架构师录制的视频录像:有Spring,MyBatis,Netty源码分析,高并发、高性能、分布式、微服务架构的原理,JVM性能优化、分布式架构等这些成为架构师必备的知识体系。还能领取免费的学习资源,目前受益良多

【示例 2】通过工厂设计模式获取接口对象

1.  package demo;
2.  interface  IMessage {    // 定义业务接口
3.  /**
4.  * 信息回显处理
5.  * @param msg 原始信息
6.  * @return 追加回显后的信息
7.  */
8.  public String  echo(String  msg);  
9.  }
10.  class  Factory {
11.  private Factory() {}    // 构造方法私有化
12.  public static IMessage  getInstance(String  className) {
13.  if ("echo".equals(className)) {
14.  return new MessageImpl() ;    // 返回接口实例
15.  }
16.  return null ;
17.  }
18.  }
19.  class  MessageImpl implements IMessage {    // 定义接口子类
20.  @Override
21.  public String  echo(String  msg) {
22.  return "【ECHO】" + msg;    // 回显处理
23.  }
24.  }
25.  public class  TestMessageDemo {
26.  public static void main(String[] args) {
27.  IMessage  message = Factory.getInstance("echo") ;    // 通过工厂类获取接口对象
28.  System.out.println(message.echo("https://mp.weixin.qq.com/mp/profile_ext?action=home&__biz=Mzg3MzczNjYzMA==&scene=124&uin=&key=&devicetype=Windows+10+x64&version=6302019c&lang=zh_CN&a8scene=7&fontgear=2"));
29.  }
30.  }

程序运行后,结果如下:

【ECHO】https://mp.weixin.qq.com/mp/profile_ext?action=home&__biz=Mzg3MzczNjYzMA==&scene=124&uin=&key=&devicetype=Windows+10+x64&version=6302019c&lang=zh_CN&a8scene=7&fontgear=2

本程序采用工厂设计模式解决了调用者与具体子类之间的耦合关联。调用者只需通过 Factory 类,就可以获取接口对象,不用再关注具体的子类是哪一个。本程序的代码结构如图 2 所示。

image.png

图 2 通过工厂类获取接口对象

虽然通过工厂设计模式可以改善接口对象的获取处理,但如果一个接口有无数个子类,且这些子类可随时动态增加,这样的静态工厂设计就会产生问题,会导致大量的修改操作。实际开发中,还需要结合反射机制来改善工厂设计。

【示例 3】利用反射机制改善工厂设计

1.  package demo;
2.  interface  IMessage {    // 定义业务接口
3.  /**
4.  * 信息回显处理
5.  * @param msg 原始信息
6.  * @return 追加回显后的信息
7.  */
8.  public String  echo(String  msg);   
9.  }
10.  class  Factory {
11.  private Factory() {}    // 构造方法私有化
12.  @SuppressWarnings("unchecked")
13.  public static  T  getInstance(String  className) {    // 通过反射实例化
14.  try {
15.  return (T) Class.forName(className).getDeclaredConstructor().newInstance();
16.  } catch (Exception  e) {
17.  return null ;
18.  }
19.  }
20.  }
21.  class  MessageImpl implements IMessage {    // 定义接口子类
22.  @Override
23.  public String  echo(String  msg) {
24.  return "【ECHO】" + msg;    // 回显处理
25.  }
26.  }
27.  public class  TestMessageDemo {
28.  public static void main(String[] args) {
29.  IMessage  message = Factory.getInstance("demo.MessageImpl") ;    // 通过工厂类获取接口对象
30.  System.out.println(message.echo("https://mp.weixin.qq.com/mp/profile_ext?action=home&__biz=Mzg3MzczNjYzMA==&scene=124&uin=&key=&devicetype=Windows+10+x64&version=6302019c&lang=zh_CN&a8scene=7&fontgear=2"));
31.  }
32.  }

程序运行后,结果如下:

【ECHO】https://mp.weixin.qq.com/mp/profile_ext?action=home&__biz=Mzg3MzczNjYzMA==&scene=124&uin=&key=&devicetype=Windows+10+x64&version=6302019c&lang=zh_CN&a8scene=7&fontgear=2

本程序通过反射机制修改了 Factory 工厂类的设计,在调用 Factory.getInstance( ) 方法时,必须明确传入子类对象的完整名称。这样设计的好处在于,工厂类不会再与某个具体的接口或子类耦合,因此更加具有通用性。本程序的代码结构如图 3 所示。

image.png

图 3  反射与工厂设计相结合

本例利用反射机制成功改良了工厂类的设计,使得程序结构更加清晰,同时避免了程序代码可能产生的耦合问题,但这样的配置依然存在着以下问题:

  1. 获取对象时需要传递完整的“包.类”名称。这样的客户端调用显然存在缺陷,最好的解决方案是追加一个配置文件,而后根据某个名称来获取对应的“包.类”名称信息,再通过反射进行加载。
  2. 配置文件不应该只简单描述“名称 = 包.类”关系,还应包含依赖关系配置。
  3. 应该更合理地实现多线程管理,避免过多的重复对象产生。

也就是说,要想实现一整套合理的对象管理容器,直接采用原生 Java 代码并不只靠一个简单的反射机制可以解决问题,还需要考虑各种对象的状态与对象管理。

Spring 的 IOC 技术可以帮助开发者减少这些设计上的思考,使其将更多精力放在核心代码的开发处理上。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值