一、Bean的Scope
Scope描述的的Spring容器如何新建Bean的实例的。
1.Spring的Scope有以下几种,通过@Scope注解来实现
(1)Singleton:一个Spring容器中只有一个Bean实例,此为Spring的默认配置,全容器共享一个实例。
(2)Prototype:每次调用新建一个Bean实例。
(3)Request:Web项目中,给每一个http request新建一个Bean实例。
(4)Session:Web项目中,给每一个http session新建一个Bean实例。
(5)GlobalSession:这个只在portal中有用,给每一个global http session新建一个Bean实例。
2.示例–演示singleton和Prototype
分别从Spring容器中获得两次Bean,判断Bean的实例是否相同。
(1)Singleton的Bean
//Singleton的Bean
@Service
public class ScopeSingletonService {
}
/**
* 默认为Singleton,相当于@Scope("singleton")
*/
(2)Prototype的Bean
//Prototype的Bean
@Service
@Scope("prototype")
public class ScopePrototypeService {
}
/**
* 每次调用新建一个Bean实例
*/
(3)配置类
//配置类
@Configuration
@ComponentScan("zhao.spring.com.SpringScope")
public class ScopeConfig {
}
(4)启动类
public class ScopeMain {
public static void main(String[] args) {
AnnotationConfigApplicationContext context=
new AnnotationConfigApplicationContext(ScopeConfig.class);
//分别取两个Bean
ScopeSingletonService s1=context.getBean(ScopeSingletonService.class);
ScopeSingletonService s2=context.getBean(ScopeSingletonService.class);
ScopePrototypeService p1=context.getBean(ScopePrototypeService.class);
ScopePrototypeService p2=context.getBean(ScopePrototypeService.class);
System.out.println("singleton的s1和s2:"+s1.equals(s2));
System.out.println("prototype的p1和p2:"+p1.equals(p2));
context.close();
}
}
二、Spring EL
Spring表达式语言,支持在xml和注解中使用表达式,类似于JSP的EL表达式语言。
Spring开发中经常涉及调用各种资源的情况,包含普通文件、网址、配置文件、系统环境变量,我们可以使用Spring的表达式语言实现资源的注入。
Spring主要在注解@Value的参数中使用表达式。
1,示例
(1)增加commons-io可简化文件相关操作,这里使用commons-io将file转换成字符串。
<!--commons-io可以简化文件相关操作-->
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.3</version>
</dependency>
新建text.txt,内容为:
这是一个txt文件
新建test.properties等待测试的配置文件
book.author=zhaoxudong
book.name=springbook
以上两个文件的存放位置:
为什么要存放在这里呢?
因为classpath的位置指向:
(2)需注入的Bean
//演示需注入的Bean
@Service
public class SpringELService {
@Value("其他类的属性")
private String another;
public String getAnother() {
return another;
}
public void setAnother(String another) {
this.another = another;
}
}
/**
* 这里注入了一个普通字符串
*/
(3)配置类
//配置类
@Configuration
@ComponentScan("com.zhao.spring.SpringEL")
//注入配置文件
@PropertySource("classpath:com/zhao/spring/SpringEL/test.properties")
public class SpringELConfig {
//注入普通字符串
@Value("this is normal")
private String normal;
//注入操作系统属性
@Value("#{systemProperties['os.name']}")
private String osName;
//注入表达式结果
@Value("#{ T(java.lang.Math).random()*100.0}")
private double randomNumber;
//注入其他Bean属性
@Value("#{springELService.another}")
private String fromAnother;
//注入文件资源
@Value("classpath:/com/zhao/spring/SpringEL/text.txt")
private Resource testFile;
//注入网址资源
@Value("http://www.baidu.com")
private Resource testUrl;
/*
注入配置文件
*/
@Value("${book.name}")
private String bookName;
@Autowired
private Environment environment;
@Bean
public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer(){
return new PropertySourcesPlaceholderConfigurer();
}
public void outputResource(){
try {
System.out.println(normal);
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);
System.out.println(environment.getProperty("book.author"));
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* 注入配置文件需要使用@PropertySource指定文件地址,若使用@Value注入,则需要配置一个PropertySourcesPlaceholderConfigurer
* 的Bean。
* 注入PropertySource还可以从Environment中获得
*/
(4)启动类
//启动类
public class SpringELMain {
public static void main(String[] args) {
AnnotationConfigApplicationContext context=
new AnnotationConfigApplicationContext(SpringELConfig.class);
SpringELConfig springELConfig=context.getBean(SpringELConfig.class);
springELConfig.outputResource();
context.close();
}
}
三、Bean的初始化和销毁
在我们实际开发的时候,经常会遇到Bean在使用之前或者之后做某些必要的操作,Spring对Bean的生命周期的操作提供了支持。在使用Java配置和注解配置下提供如下两种方法。
(1)Java配置:使用@Bean的initMethod和destroyMethod(相当于xml配置的init-method和destroy-method)
(2)注解方式:利用JSR-250的@PostConstruct和@PreDestroy
1.演示
(1)增加JSR250支持
<!--增加JSR250支持-->
<dependency>
<groupId>javax.annotation</groupId>
<artifactId>jsr250-api</artifactId>
<version>1.0</version>
</dependency>
(2)使用@Bean形式的Bean
public class BeanWayService {
public void init(){
System.out.println("@Bean--init-method");
}
public BeanWayService() {
System.out.println("初始化构造函数--BeanWayService");
}
public void destroy(){
System.out.println("@Bean--destroy-method");
}
}
(3)使用JSR250形式的Bean
@Service
public class JSR250WayService {
@PostConstruct
public void init(){
System.out.println("JSR250--init-method");
}
public JSR250WayService() {
System.out.println("初始化构造函数--JSR250WayService");
}
@PreDestroy
public void destroy(){
System.out.println("JSR250--destroy-method");
}
}
/**
* @PostConstruct 在构造函数执行完之后执行
* @PreDestroy 在Bean销毁之前执行
*/
(4)配置类
//配置类
@Configuration
@ComponentScan("com.zhao.spring.BeanInitDestroy")
public class BeanInitDestroyConfig {
@Bean(initMethod = "init",destroyMethod = "destroy")
BeanWayService beanWayService(){
return new BeanWayService();
}
}
/**
* initMethod和destroyMethod指定BeanWayService类的init和destroy方法在构造之后、Bean销毁之前执行
*/
(5)启动类
public class BeanInitDestroyMain {
public static void main(String[] args) {
AnnotationConfigApplicationContext context=
new AnnotationConfigApplicationContext(BeanInitDestroyConfig.class);
BeanWayService beanWayService=context.getBean(BeanWayService.class);
JSR250WayService jsr250WayService=context.getBean(JSR250WayService.class);
context.close();
}
}