[spring]從頭開始-Configuration Using Java Classes
開發工具:IntelliJ IDEA 13
開發環境:jdk1.6.0_45
Framework:spring 3
之前都用xml的方式來配置spring configuration file,現在我們使用java code 的方式來達成一樣的效果,建立一個 Provider 相依於 Renderer 的範例。先建立一個 Provider:
MessageProvider.java
package foo.bar;
/**
* Created by Hsu on 2014/7/16.
*/
public interface MessageProvider {
public String getMessage();
}
再建立一個implement 類別:
ConfigurableMessageProvider.java
package foo.bar;
/**
* Created by Hsu on 2014/7/16.
*/
public class ConfigurableMessageProvider implements MessageProvider {
private String message = "Default message";
public ConfigurableMessageProvider() {
}
public ConfigurableMessageProvider(String message) {
this.message = message;
}
public void setMessage(String message) {
this.message = message;
}
@Override
public String getMessage() {
return this.message;
}
}
接著建立 Renderer 類:
MessageRenderer.java
package foo.bar;
/**
* Created by Hsu on 2014/7/16.
*/
public interface MessageRenderer {
public void render();
public void setMessageProvider(MessageProvider provider);
public MessageProvider getMessageProvider();
}
一樣再建立一個 Renderer 的 implement 類:
StandardOutMessageRenderer.java
package foo.bar;
/**
* Created by Hsu on 2014/7/16.
*/
public class StandardOutMessageRenderer implements MessageRenderer {
private MessageProvider messageProvider = null;
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());
}
public void setMessageProvider(MessageProvider provider){
this.messageProvider = provider;
}
public MessageProvider getMessageProvider() {
return this.messageProvider;
}
}
接著使用 xml 配置出上面的相依關係
spring-config.xml
..
..標頭的部分省略
<bean id="messageRenderer"
class="foo.bar.StandardOutMessageRenderer"
p:messageProvider-ref="messageProvider"/>
<bean id="messageProvider"
class="foo.bar.ConfigurableMessageProvider"
c:message="This is a configurable message"/>
..結尾省略
上面配置檔的部分有使用 p 標籤 及 c 標籤,記得要引入相關的標頭,這邊順道回憶一下它們的主要作用:
p: The pnamespace provides a simpler DI configuration for Setter Injection.
c: New in Spring 3.1, the cnamespace provides a more simple DI configuration for Constructor Injection.
p 就是使用在 setter 的部份,c是使用在 Constructor inject 的部份。
最後是演繹類別的部份:
JavaConfigSimpleExample.java
package foo.bar;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* Created by Hsu on 2014/7/16.
*/
public class JavaConfigSimpleExample {
public static void main(String[] args) {
ApplicationContext ctx = new
ClassPathXmlApplicationContext("classpath:spring-config.xml");
MessageRenderer renderer =
ctx.getBean("messageRenderer", MessageRenderer.class);
renderer.render();
}
}
簡單介紹一下上面範例的概念,提供者 provider 可以有很多種不同的提供者(看implement出哪種提供者),而 renderer(渲染器或稱為解析器)也可以有很多種,依照 provider 的不同而選擇不同的 renderer 將資訊送出。
上述範例的執行結果:
This is a configurable message
就是我們在 xml 配置檔中所 inject 的訊息。接著我們使用 java code 來配置。
AppConfig.java
package foo.bar;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* Created by Hsu on 2014/7/16.
*/
// 宣告這個類別是一個配置檔
@Configuration
public class AppConfig {
// XML:
// <bean id="messageProvider" class="foo.bar.ConfigurableMessageProvider"/>
// new ConfigurableMessageProvider("Test Message") like c:message="This is a configurable message"
@Bean
public MessageProvider messageProvider() {
return new ConfigurableMessageProvider("Test Message");
}
// XML:
// <bean id="messageRenderer" class=""foo.bar.StandardOutMessageRenderer"
// p:messageProvider-ref="messageProvider"/>
@Bean
public MessageRenderer messageRenderer() {
MessageRenderer renderer = new StandardOutMessageRenderer();
// Setter injection
renderer.setMessageProvider(messageProvider());
return renderer;
}
}
上面我們可以看到要完成 java code 來配置,需引入 org.springframework.context.annotation.Bean 及 org.springframework.context.annotation.Configuration ,類別中使用 @Configuration 宣告該類別為一個配置檔,接著在類別中使用 @Bean 來宣告 bean,bean 的內容同我們之前的 xml 配置檔內容,相關的對應都已經註明在程式中,看到就應該可以了解
最後我們來完成演繹類別
JavaConfigSimpleExample1.java
public class JavaConfigSimpleExample1 {
public static void main(String[] args) {
ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);
// 採用 Autowire
//ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig2.class);
MessageRenderer renderer =
ctx.getBean("messageRenderer", MessageRenderer.class);
renderer.render();
}
}
執行結果:
Test Message
上面的演繹類別有注意到還有一個 AppConfig2.class 被註解起來了,這是準備使用 Autowire 來完成同樣效果的。
檔案內容如下:
AppConfig2.java
package foo.bar;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.*;
import org.springframework.core.env.Environment;
import org.springframework.transaction.annotation.EnableTransactionManagement;
/**
* Created by Hsu on 2014/7/16.
*/
@Configuration
//
// @Import(OtherConfig.class)
// XML: <import resource="classpath:spring-config2.xml")
@ImportResource(value="classpath:spring-config2.xml")
// XML: <context:property-placeholder location="classpath:message.properties"/>
@PropertySource(value="classpath:message.properties")
// XML: <context:component-scan base-package="foo.bar"/>
@ComponentScan(basePackages={"foo.bar"})
// @EnableTransactionManagement defines that we will use Spring’s transaction management feature
@EnableTransactionManagement
public class AppConfig2 {
@Autowired
// spring 3.1.x new add
Environment env;
// XML:
// <bean id="messageProvider" class="foo.bar.ConfigurableMessageProvider"/>
@Bean(name="messageProvider")
//XML <bean .... lazy-init="true"/> The @Lazy annotation instructs Spring to instantiate the bean only when requested
@Lazy(value=true)
public MessageProvider messageProvider() {
// Constructor injection
return new ConfigurableMessageProvider(env.getProperty("message"));
}
// XML:
// <bean id="messageRenderer" class="foo.bar.StandardOutMessageRenderer"
// p:messageProvider-ref="messageProvider"/>
@Bean(name="messageRenderer")
@Scope(value="prototype") // XML: <bean ... scope="prototype"/>
@DependsOn(value="messageProvider") // XML: <bean ... depends-on="messageProvider"/>
public MessageRenderer messageRenderer() {
MessageRenderer renderer = new StandardOutMessageRenderer();
// Setter injection
renderer.setMessageProvider(messageProvider());
return renderer;
}
}
搭配的 spring configuration file:
spring-config2.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"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:c="http://www.springframework.org/schema/c"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<context:annotation-config />
<context:component-scan base-package="foo.bar"/>
</beans>
message.properties 的內容
message=Spring 3 Java Configuration Rocks!
範例執行結果:
Spring 3 Java Configuration Rocks!
可以看到上面是完全使用 Annotation 來完成 java config code 的設定,並由 message.properties 讀取 provider 的 message,程式碼中皆有註解,可以輕易了解用途,其中注意的是 使用 env.getProperty("message") 來讀取 properties 的資料,跟我們之前所用的 ctx.getMessage("msg", null, english) 有些許的不同,需要特別注意一下
getPropertyString getProperty(String key) Return the property value associated with the given key, or null if the key cannot be resolved. Parameters: key - the property name to resolve See Also: getProperty(String, String), getProperty(String, Class), getRequiredProperty(String) |