Spring轻量级开发---基础知识和初体验

1.首先先来看看最简单的hello world程序

public static void main(String[] args){    
    System.out.println("HelloWorld");
}

2.如果需要修改输出的字符串的内容,需要重新编译代码和测试相关联的功能,这是很不合理和危险的。一个更好的解决方案是让程序接收外部消息字串,这样就可以在运行时决定输出的内容。

public static void main(String[] args){
    if(args.length>0)
        System.out.println(args[0]);
    else
        System.out.println("HelloWorld");
}

3.这样的修改可以让我们改变输出的字串,这是一个进步。但观察这个程序,有两个功能:取得外部参数、输出字串

这两个功能被捆绑在一起,这是过程化的思维方式。所以我们需要分离职责

为了使程序的架构更灵活,我们应该将这两个职责装入不同的组件里,可以使用接口来实现两个不同的职责。而主程序main只和这两个组件接口打交道。

首先建两个接口

 1 public interface IMessageDisplayer {
 2     /**
 3      * 消息显示者接口
 4      */
 5     void display();
 6     
 7     /**
 8      * 
 9      * 提供get/set方法
10      */
11     void setIMessageSupplier(IMessageSupplier s);
12     IMessageSupplier getIMessageSupplier();
13 }
1 public interface IMessageSupplier {
2     /**
3      * 取得消息
4      */
5     String getMessage();
6 }

然后分别给出这两个类的实现

 1 public class HelloWorldDisplayer implements IMessageDisplayer {
 2 
 3     private IMessageSupplier messageSupplier=null;
 4     
 5     public void display() {
 6         if(null==messageSupplier){
 7             throw new RuntimeException("messageSupplier为空");
 8         }
 9         System.out.println(messageSupplier.getMessage());
10     }
11 
12     public IMessageSupplier getIMessageSupplier() {
13         return messageSupplier;
14     }
15 
16     public void setIMessageSupplier(IMessageSupplier s) {
17         this.messageSupplier=s;
18     }
19 }
1 public class HelloWorldSupplier implements IMessageSupplier{
2     public String getMessage(){
3         return "HelloWorldSup";
4     }
5 }

然后重构下主程序即可

 1 public class HelloWorldBetter {
 2     /**
 3      * 初步重构HelloWorld之后的主程序体
 4      * 解耦了消息显示者和消息提供者这两个职责
 5      */
 6     public static void main(String[] args) {
 7         //创建消息显示者
 8         IMessageDisplayer messageDisplayer=new HelloWorldDisplayer();
 9         //创建消息提供者
10         IMessageSupplier messageSupplier=new HelloWorldSupplier();
11         //注入消息提供者
12         messageDisplayer.setIMessageSupplier(messageSupplier);
13         //显示消息
14         messageDisplayer.display();
15     }
16 }

4.经过这样重构后,我们的成果已经比较成功了。但仍存在一些问题,如果想替换接口的实现类,则依然需要在程序中手动改动代码,那么程序代码依然要经历重新编译测试的风险,为了克服这一缺点,可以引入单例工厂(Singleton Factory)

我们首先创建一个单例工厂类

 1 /**
 2  * Message组件生产工厂,这是一个单例类
 3  * 通过读取外部属性文件msgbean.properties
 4  * 获取MessageDisplayer和MessageSupplier的实现类名
 5  * 并由工厂创建各自的实例
 6  */
 7 public class MessageSupporterFactory {
 8 
 9         /**
10          * 全局单一的工厂实例 注意需要静态
11          */
12         private static MessageSupporterFactory factory=null;
13         
14         /**
15          * 外部属性
16          */
17         private static Properties props;
18         
19         /**
20          * 创建MessageSupportFactory单例方法
21          * 使用Synchronized保障线程安全
22          */
23         public synchronized static MessageSupporterFactory getInstance()   {
24             if(factory==null)
25                 factory=new MessageSupporterFactory();
26             return factory;
27         }
28         private MessageSupporterFactory(){
29             props=new Properties();
30             try{
31                 props.load(new FileInputStream("conf/ch2/msgbean.properties"));
32             }catch(Exception e){
33                 e.printStackTrace();
34             }
35         }
36         
37         /**
38          * 产生IMessageDisplayer的工厂方法
39          */
40         public IMessageDisplayer makeMessageDisplayer(){
41             //读取IMessagePlayer具体的实现名字
42             String displayClass=props.getProperty("display.class");
43             try {
44                 return (IMessageDisplayer)Class.forName(displayClass).newInstance();
45             } catch (InstantiationException e) {
46                 System.out.println("can not instantiate an object of type "+displayClass);
47                 e.printStackTrace();
48             } catch (IllegalAccessException e) {
49                 System.out.println("can not access class "+displayClass);
50                 e.printStackTrace();
51             } catch (ClassNotFoundException e) {
52                 System.out.println("can not find the class "+displayClass);
53                 e.printStackTrace();
54             }
55             return null;
56         }
57         
58         /**
59          * 产生IMessageSupplier的工厂方法
60          */
61         public IMessageSupplier makeMessageSupplier(){
62             //读取IMessageSupplier具体的实现名字
63             String supplyClass=props.getProperty("supply.class");
64             try {
65                 return (IMessageSupplier)Class.forName(supplyClass).newInstance();
66             } catch (InstantiationException e) {
67                 System.out.println("can not instantiate an object of type "+supplyClass);
68                 e.printStackTrace();
69             } catch (IllegalAccessException e) {
70                 System.out.println("can not access class "+supplyClass);
71                 e.printStackTrace();
72             } catch (ClassNotFoundException e) {
73                 System.out.println("can not find the class "+supplyClass);
74                 e.printStackTrace();
75             }
76             return null;
77         }
78 }

然后只要创建properties文件即可。

display.class=ch2.HelloWorldDisplayer;
supply.class=ch2.HelloWorldSupplier;

现在只需要稍微修改一下主程序main就可以达到预期效果了。

 1 public class HelloWorldBetterWithFactory {
 2     public static void main(String[] args) {
 3         //创建消息显示者
 4         IMessageDisplayer messageDisplayer=MessageSupporterFactory.getInstance().makeMessageDisplayer();
 5         //创建消息提供者
 6         IMessageSupplier messageSupplier=MessageSupporterFactory.getInstance().makeMessageSupplier();
 7         //注入消息提供者
 8         messageDisplayer.setIMessageSupplier(messageSupplier);
 9         //显示消息
10         messageDisplayer.display();
11     }
12 }

程序中通过读取配置文件获得类名,并通过反射获取类的实例,从而实现输出的目的。尽管一个hello world程序不需要这么繁琐地做修改,但其中的道理却很有用: 为避免程序重新编译测试的风险,我们应该尽量把程序的责任分离,降低耦合度。而工厂模式和反射则是一个降低耦合度的很好用的方法。

原文地址:https://www.cnblogs.com/elenno/p/SpringTest.html