1.经典的helloworld案例
该例非常简单, 它可以完成相关工作,但不具有可扩展性。
public class HelloWorldWithCommandLine { public static void main(String[] args) { // TODO Auto-generated method stub if (args.length > 0) { System.out.println(args[0]); } else { System.out.println("Hello world"); } } }
该例完成了所需的功能,现在可以在不更改代码的情况下更改消息。但是 , 这个应用程序仍然存在问题: 负责渲染消息的组件同时也负责获取消息。
package spring; public interface MessageProvider { String getMessage(); }
package spring; public interface MessageRenderer { void render(); void setMessageProvider(MessageProvider provider); MessageProvider getMessageProvider(); }
package spring; import javax.management.RuntimeErrorException; public class StandardOutMessageRenderer implements MessageRenderer { private MessageProvider messageProvider; @Override public void render() { // TODO Auto-generated method stub if (messageProvider == null) { throw new RuntimeException("You must set the property messageProvider of class :" + StandardOutMessageRenderer.class.getName()); } System.out.println(messageProvider.getMessage()); } @Override public void setMessageProvider(MessageProvider provider) { // TODO Auto-generated method stub this.messageProvider = provider; } @Override public MessageProvider getMessageProvider() { // TODO Auto-generated method stub return this.messageProvider; } }
package spring; public class HelloWorldDecoupled { public static void main(String... args) { MessageRenderer mr = new StandardOutMessageRenderer(); MessageProvider mp = new HelloWorldMessageProvider(); mr.setMessageProvider(mp); mr.render(); } }
此时的代码非常简单。我们实例化了 HelloWorld.MessageProvider 和 StandardOutMessageRenderer 的实例,虽然声明的类型分别是 MessageProvider 和 MessageRenderer 。这是因为只需要在编程逻辑中与接口提供的方法进行交互,并且 HelloWorld.MessageProvider 和 StandardOutMessageReriderer 已经分别实现了这些接口 。 然后,将 MessageProvider传递给 MessageRenderer 并调用 MessageRenderer.render()。 如果编译并运行该程序,将会得到预期的 “Hello World !”输出。
现在, 该例更能满足我们的要求,但存在一个小问题。 更改 MessageRenderer 或 MessageProvider 接口的实现意味着对代码进行更改。 为了解决这个问题,可以创建一个简单的工厂类,它从属性文件中读取实现类的名称,并代表应用程序对它们进行实例化。
package spring; import java.util.Properties; import java.util.Set; public class MessageSupportFactory { private static MessageSupportFactory instance; private Properties props; private MessageRenderer renderer; private MessageProvider provider; private MessageSupportFactory() { // TODO Auto-generated constructor stub props = new Properties(); try { props.load(this.getClass().getResourceAsStream("/msf.properties")); Set set = props.keySet(); String rendererClass = props.getProperty("renderer.class"); String providerClass = props.getProperty("provider.class"); renderer = (MessageRenderer) Class.forName(rendererClass).newInstance(); provider = (MessageProvider) Class.forName(providerClass).newInstance(); } catch (Exception e) { // TODO: handle exception e.printStackTrace(); } } static { instance = new MessageSupportFactory(); } public static MessageSupportFactory getinstance() { return instance; } public MessageRenderer getMessageRenderer() { return renderer; } public MessageProvider getMessageProvider() { return provider; } }
renderer.class=spring.StandardOutMessageRenderer provider.class=spring.HelloWorldMessageProvider
package spring; public class HelloWorldDecoupled { public static void main(String... args) { MessageRenderer mr = MessageSupportFactory.getinstance().getMessageRenderer(); MessageProvider mp = MessageSupportFactory.getinstance().getMessageProvider(); mr.setMessageProvider(mp); mr.render(); } }
用 Spring 重构
xml方式进行重构
package spring; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class HelloWorldSpringDI { public static void main(String[] args) { ApplicationContext ctx = new ClassPathXmlApplicationContext("test/spring/app-context.xml "); MessageRenderer mr = ctx.getBean("renderer", MessageRenderer.class); mr.render(); } }
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans" xmlns:p="http://www.springframework.org/schema/p" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd "> <bean id="provider" class="test.spring.HelloWorldMessageProvider" /> <bean id="renderer" class="test.spring.StandardOutMessageRenderer" p:messageProvider-ref="provider"/> </beans>
注解方式进行重构
package spring;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class HelloWorldConfiguration {
@Bean
public MessageProvider provider() {
return new HelloWorldMessageProvider();
}
@Bean
public MessageRenderer renderer() {
MessageRenderer renderer = new StandardOutMessageRenderer();
renderer.setMessageProvider(provider());
return renderer;
}
}
package spring;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class HelloWorldSpringDI {
public static void main(String[] args) {
ApplicationContext ctx = new AnnotationConfigApplicationContext(HelloWorldConfiguration.class);
MessageRenderer mr = ctx.getBean("renderer", MessageRenderer.class);
mr.render();
}
}