Spring常用配置介紹
- Scope
- PropertySource
- Bean的初始化與銷毀
- Profile
- Application Event
【Scope】
- Singleton:一個容器中只有一個,為預設
- Prototype:每次都建立新的
- Request:一個 http request 一個
- Session:一個 http session 一個
- GlobalSession:一個 global http session 一個
- @StepScope:Spring Batch中使用
【範例】
- Singleton Bean
@Service // 預設為Singleton,不寫等同於@Scope("singleton")
public class DemoSingletonService {
}
- Prototype Bean
@Service
@Scope("prototype") // 設定scope為prototype
public class DemoPrototypeService {
}
- Configuration
@Configuration
@ComponentScan("com.myPackage")
public class ScopeConfig {
}
- Context
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class Main {
public static void main(String[] args) {
AnnotationConfigApplicationContext context =
new AnnotationConfigApplicationContext(ScopeConfig.class);
DemoSingletonService s1 = context.getBean(DemoSingletonService.class);
DemoSingletonService s2 = context.getBean(DemoSingletonService.class);
DemoPrototypeService p1 = context.getBean(DemoPrototypeService.class);
DemoPrototypeService p2 = context.getBean(DemoPrototypeService.class);
System.out.println(s1.equals(s2)); // true
System.out.println(p1.equals(p2)); // false
context.close();
}
}
【Spring EL 及資源調用】
- @PropertySource:讀取property檔內容
- @Value:注入值的方式
- @Value("#{systemProperties['os.name']}"):注入系統屬性
- @Value("#{ T(java.lang.Math).random() * 100.0 }):注入運算式
- @Value("${book.name}"):注入讀取的property中的內容
【範例】
- test.properties
book.author = AAA
book.name = spring boot
- Service
@Service
public class DemoService {
@Value("其他類的屬性") // 注入String
private String another;
public String getAnother() {
return another;
}
public void setAnother(String another) {
this.another = another;
}
}
- Configuration
@Configuration
@ComponentScan("com.myPackage")
@PropertySource("classpath:com/myPackage/test.properties") // 指定property檔的位置
public class ElConfig {
@Value("I Love You!") // 注入String
private String normal;
@Value("#{systemProperties['os.name']}") // 注入系統屬性
private String osName;
@Value("#{ T(java.lang.Math).random() * 100.0 }") // 注入運算式
private double randomNumber;
@Value("#{demoService.another}") // 注入其他類之屬性
private String fromAnother;
@Value("classpath:com/myPackage/test.txt") // 注入文件資源
private Resource testFile;
@Value("http://www.baidu.com") // 注入網址資源
private Resource testUrl;
@Value("${book.name}") // 注入property檔內容
private String bookName;
@Autowired
private Environment environment; // 也可透過Environment取得property檔中的內容
@Bean // 使用@Value注入property檔內容時,要有此配置
public static PropertySourcesPlaceholderConfigurer propertyConfigure() {
return new PropertySourcesPlaceholderConfigurer();
}
public void outputResource() {
try {
System.out.println(normal); // I Love You!
System.out.println(osName); // 系統名稱
System.out.println(randomNumber); // 隨機數字
System.out.println(fromAnother); // 其他類的屬性
System.out.println(IOUtils.toString(testFile.getInputStream())); // 文件內容
System.out.println(IOUtils.toString(testUrl.getInputStream())); // 網站內容
System.out.println(bookName); // Spring Boot
System.out.println(environment.getProperty("book.author")); // 透過Environment取得內容 AAA
} catch (Exception e) {
e.printStackTrace();
}
}
}
【Bean的初始化及銷毀】
- Java配置:@Bean的initMethod、destroyMethod
- 註解:JSR-250中的@PostConstruct、@PreDestroy
【範例】
- Java配置的Bean
public class BeanWayService {
public void init(){
System.out.println("Bean init method");
}
public BeanWayService() {
super();
System.out.println("初始化BeanWayService");
}
public void destroy(){
System.out.println("Bean destroy method");
}
}
- JSR-250的Bean
public class JSR250WayService {
@PostConstruct // 建立Bean之後執行
public void init(){
System.out.println("jsr250 init method");
}
public JSR250WayService() {
super();
System.out.println("初始化JSR250WayService");
}
@PreDestroy // Bean銷毀前執行
public void destroy(){
System.out.println("jsr250 destory method");
}
}
- Configuration
@Configuration
@ComponentScan("com.myPackage")
public class PrePostConfig {
// 指定beanWayService的init及destroy方法,於Bean建立後、銷毀前執行
@Bean(initMethod="init",destroyMethod="destroy")
BeanWayService beanWayService(){
return new BeanWayService();
}
@Bean
JSR250WayService jsr250WayService(){
return new JSR250WayService();
}
}
- Context
public class Main {
public static void main(String[] args) {
AnnotationConfigApplicationContext context =
new AnnotationConfigApplicationContext(PrePostConfig.class);
BeanWayService beanWayService = context.getBean(BeanWayService.class);
JSR250WayService jsr250WayService = context.getBean(JSR250WayService.class);
context.close();
}
}
【Profile】
Profile目的為方便在不同環境下,使用不同配置(如:開發環境與生產環境的資料庫配置),方法有三:
- 透過Environment的ActiveProfiles設定當前使用的Profile,實例化不同的Bean
- 透過設定jvm的spring.profiles.active參數設置
<servlet> <servlet-name>dispatcher</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>spring.profiles.active</param-name> <param-value>production</param-value> </init-param> </servlet>
- Web中設置在Servlet的context parameter中
public class WebInit implenments WebApplicationInitializer { @Override public void onStartup(ServletContext container) throws ServletException { container.setInitParameter("spring.profiles.default", "dev"); } }
【範例】
- Bean
public class DemoBean {
private String content;
public DemoBean(String content) {
super();
this.content = content;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
}
- Configuration
@Configuration
public class ProfileConfig {
@Bean
@Profile("dev") // 用Profile註釋,設定為開發用
public DemoBean devDemoBean() {
return new DemoBean("from development profile");
}
@Bean
@Profile("prod") // 生產用
public DemoBean prodDemoBean() {
return new DemoBean("from production profile");
}
}
- Context
public class Main {
public static void main(String[] args) {
AnnotationConfigApplicationContext context =
new AnnotationConfigApplicationContext();
// 透過Environment,選擇要實例化的Bean
context.getEnvironment().setActiveProfiles("dev");
context.register(ProfileConfig.class); // 後置註冊Configuration,不然會報Bean未定義的錯誤
context.refresh(); // 刷新容器
DemoBean demoBean = context.getBean(DemoBean.class);
System.out.println(demoBean.getContent());
context.close(); // 印出 from development profile
}
}
【Application Event】
替Bean和Bean之間的消息通信提供支持,透過讓Bean監聽另一Bean發送的事件,能夠做相應的處理。
【範例】
- Bean ( Event )
// 事件需繼承 ApplicationEvent
public class DemoEvent extends ApplicationEvent{
private static final long serialVersionUID = 1L;
private String msg;
public DemoEvent(Object source,String msg) {
super(source);
this.msg = msg;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
}
- 監聽器
@Component
// 需實現ApplicationListener,並指定事件類型
public class DemoListener implements ApplicationListener<DemoEvent>{
// 使用onApplicationEvent方法,對事件消息進行接受處理
public void onApplicationEvent(DemoEvent event) {
String msg = event.getMsg();
System.out.println("接收到publisher發送的訊息:" + msg);
}
}
- 事件發布
@Component
public class DemoPublisher {
@Autowired
ApplicationContext applicationContext; // 用ApplicationContext發布事件
public void publish(String msg){
// 透過publishEvent方法發布
applicationContext.publishEvent(new DemoEvent(this, msg));
}
}
- Configuration
@Configuration
@ComponentScan("com.myPackage")
public class EventConfig {
}
- Context
public class Main {
public static void main(String[] args) {
AnnotationConfigApplicationContext context =
new AnnotationConfigApplicationContext(EventConfig.class);
DemoPublisher demoPublisher = context.getBean(DemoPublisher.class);
demoPublisher.publish("hello"); // 印出 接收到publisher發送的訊息:hello
context.close();
}
}