spring引入
第一行代码升级版--helloworld
/**
* 升级版的HelloWorld,可以在不更改代码的情况下更改消息
* 但负责渲染消息的组件也负责获取消息
*/
public class HelloWorld {
public static void main(String[] args){
if (args.length>0){
System.out.println(args[0]);
}else {
System.out.println("HelloWorld!");
}
}
}
helloworld解耦,消息提供与渲染分离
/**
* 消息提供者
*/
public interface MessageProvider {
String getMessage();
}
/**
* 消息渲染
*/
public interface MessageRenderer {
void render();
void setMessageProvider(MessageProvider provider);
MessageProvider getMessageProvider();
}
public class HelloWorldMessageProvider implements MessageProvider {
@Override
public String getMessage() {
return "Hello World!";
}
}
public class StandardOutMessageRenderer implements MessageRenderer {
private MessageProvider messageProvider;
@Override
public void render() {
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) {
this.messageProvider = provider;
}
@Override
public MessageProvider getMessageProvider() {
return this.messageProvider;
}
}
public class HelloWorldDecoupled {
public static void main(String[] args){
MessageRenderer mr = new StandardOutMessageRenderer();
MessageProvider mp = new HelloWorldMessageProvider();
mr.setMessageProvider(mp);
mr.render();
}
}
虽然解耦,但更改接口的实现意味着更改代码,解决这个问题可以创建一个简单的工厂
msf.properties
renderer.class=com.anocation.helloword.StandardOutMessageRenderer
provider.class=com.anocation.helloword.HelloWorldMessageProvider
/**
* 消息工厂
*/
public class MessageSupportFactory {
private static MessageSupportFactory instance;
private Properties props;
private MessageRenderer renderer;
private MessageProvider provider;
public MessageSupportFactory() {
props = new Properties();
try {
props.load(this.getClass().getResourceAsStream("/msf.properties"));
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) {
e.printStackTrace();
}
}
static {
instance = new MessageSupportFactory();
}
public static MessageSupportFactory getInstance(){
return instance;
}
public MessageRenderer getMessageRenderer(){
return renderer;
}
public MessageProvider getMessageProvider(){
return provider;
}
}
public class HelloWorldDecoupledWithFactory {
public static void main(String[] args){
MessageProvider mp = MessageSupportFactory.getInstance().getMessageProvider();
MessageRenderer mr = MessageSupportFactory.getInstance().getMessageRenderer();
mr.setMessageProvider(mp);
mr.render();
}
}
使用spring
前面但仍然存在问题,第一个问题是必须编写大量的粘合代码将应用程序拼凑在一起,同时保持组件松祸合。第二个问题是仍然需要手动提供 MessageProvider 实例的 MessageRenderer 实现
app-config.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="provider" class="com.anocation.helloword.HelloWorldMessageProvider"/>
<!--renderer 依赖MessageProvider接口来获取需要渲染的消息-->
<bean id="renderer"
class="com.anocation.helloword.StandardOutMessageRenderer">
<property name="messageProvider" ref="provider"/>
</bean>
</beans>
public class HelloWorldSpringDI {
public static void main(String[] args){
ApplicationContext ctx = new ClassPathXmlApplicationContext("app-config.xml");
MessageRenderer mr = ctx.getBean("renderer", MessageRenderer.class);
mr.render();
}
}
使用注解方式
@Configuration
public class HelloWorldConfiguration {
@Bean
public MessageProvider provider(){
return new HelloWorldMessageProvider();
}
@Bean
public MessageRenderer renderer(){
MessageRenderer renderer = new StandardOutMessageRenderer();
renderer.setMessageProvider(provider());
return renderer;
}
}
public class HelloWorldSpringAnnotated {
public static void main(String[] args){
ApplicationContext ctx = new AnnotationConfigApplicationContext(HelloWorldConfiguration.class);
MessageRenderer mr = ctx.getBean("renderer", MessageRenderer.class);
mr.render();
}
}