Spring高级配置(一)—bean的作用域
一、Spring中的单例Bean
1、Spring框架中的Bean,或者说组件,获取实例的时候都是默认单例模式,也就是表示Spring Bean容器(ApplicationContext)中仅有一个实例。
(1)、创建一个bean对象
(2)、创建spring配置文件applicationContext.xml文件,并配置一个bean对象。
(3)、测试
(4)、打印输出
结论:当bean的作用域为默认即单例时,无论我们是否主动获取bean对象,spring上下文一加载就会创建bean对象
(5)、获取bean测试
(6)、测试
结论:无论获取多少次,得到的都是同一对象
(7)、注入多个bean
(8)、测试
结论:无论注入多少次,得到的都是同一对象
二、Bean的作用域
spring中bean的作用域有以下几种:
1、singleton:Spring容器内只存在一个Bean实例,即单例模式,是系统默认值。
2、prototype:多例模式,每次调用都会创建一个Bean 也就是每次getBean()就相当于是new Bean()的操作
注意:prototype的作用域需要慎重考虑 因为每次创建和销毁都会造成很大的性能开销
WEB环境下的作用域:
3、request : 每次HTTP请求都会创建一个Bean
4、session : HTTP Session共享一个Bean实例
5、global-session:用于 portlet 容器,因为每个 portlet 有单独的 session,globalsession 提供一个全局性的 http session。
上文中的测试为系统默认,也就是单例模式,下面对prototype多例模式进行测试:
三、使用xml配置
1、创建一个bean对象
public class Demo {
public Demo() {
System.out.println("构造函数....." + this.toString());
}
}
2、在ApplicationContext.xml中配置bean
<?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">
<!--使用scope属性配置bean的作用域-->
<bean id="demo" class="com.bean.Demo" scope="prototype" ></bean>
</beans>
3、测试:bean对象的获取
(1)、使用测试类的形式,加载上下文,不获取bean对象
public class DemoTest2 {
@Test
public void test(){
ApplicationContext context = new ClassPathXmlApplicationContext("ApplicationContext.xml"); // Demo demo1 = (Demo) context.getBean("demo");
// Demo demo2 = (Demo) context.getBean("demo");
// System.out.println(demo1);
// System.out.println(demo2);
// System.out.println(demo1 == demo2);
}
}
测试输出:
Process finished with exit code 0
(2)、使用测试类的形式,加载上下文,获取bean对象
public class DemoTest2 {
@Test
public void test(){
ApplicationContext context = new ClassPathXmlApplicationContext("ApplicationContext.xml");
Demo demo1 = (Demo) context.getBean("demo");
Demo demo2 = (Demo) context.getBean("demo");
System.out.println(demo1);
System.out.println(demo2);
System.out.println(demo1 == demo2);
}
}
测试输出:
构造函数.....com.bean.Demo@f5090e
构造函数.....com.bean.Demo@14e5011
com.bean.Demo@f5090e
com.bean.Demo@14e5011
false
结论: 当bean的作用域为 scope="prototype"时,
1、spring上下文在加载时不会创建bean对象;
2、每次获取bean,都会得到不同的对象;
(3)、使用主类的形式,加载上下文,获取bean对象
public class ApplicationSpring {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("ApplicationContext.xml");
Demo demo1 =(Demo) context.getBean("demo");
Demo demo2 =(Demo) context.getBean("demo");
System.out.println(demo1);
System.out.println(demo2);
System.out.println(demo1 == demo2);
}
}
测试结果与上面一致:
构造函数.....com.bean.Demo@4a765
构造函数.....com.bean.Demo@17d0578
com.bean.Demo@4a765
com.bean.Demo@17d0578
false
(4)、bean的注入
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:ApplicationContext.xml")
public class DemoTest1 {
@Autowired
private Demo demo1;
@Autowired
private Demo demmo2;
@Test
public void test() {
System.out.println(demo1 ==demmo2);
}
}
测试输出:
构造函数.....com.bean.Demo@16be40f
构造函数.....com.bean.Demo@1be656f
false
结论: 当bean的作用域为 scope="prototype"时,
1、spring上下文在加载时不会创建bean对象;
2、每次注入bean,都会得到不同的对象;
四、使用注解配置
1、创建一个bean对象,使用注解@Scope(value = “prototype”),声明bean为一个多例
@Component
//@Scope(value = "prototype")
//@Scope("prototype") 这几种方法都可以
//@Scope(scopeName = "prototype")
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class Demo {
public Demo() {
System.out.println("构造函数....." + this.toString());
}
}
2、创建一个配置类
@ComponentScan
@Configuration
public class SpringConfig {
}
3、测试bean对象的获取
public class ApplicationSpring {
public static void main(String[] args) {
ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);
Demo demo1 =(Demo) context.getBean("demo");
Demo demo2 =(Demo) context.getBean("demo");
System.out.println(demo1);
System.out.println(demo2);
System.out.println(demo1 == demo2);
}
}
测试输出:
构造函数.....com.bean.Demo@8c94da
构造函数.....com.bean.Demo@62b5bc
com.bean.Demo@8c94da
com.bean.Demo@62b5bc
false
结论与上面一致
4、测试bean对象的注入
RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = SpringConfig.class)
public class DemoTest1 {
@Autowired
private Demo demo1;
@Autowired
private Demo demmo2;
@Test
public void test() {
System.out.println(demo1 ==demmo2);
}
}
测试输出:
构造函数.....com.bean.Demo@2db68f
构造函数.....com.bean.Demo@3668d4
false
结论与上面一致
五、使用javaconfig配置
1、创建一个bean对象
public class Demo1 {
public Demo1() {
System.out.println("构造函数....." + this.toString());
}
}
二、创建一个配置类
@Configuration //声明这是一个配置类
public class ApplicationConfig {
@Bean
@Scope("prototype")
public Demo1 demo1(){
return new Demo1();
}
}
三、测试输出
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = ApplicationConfig.class)
public class DemoTest3 {
@Autowired
private Demo1 demo1;
@Autowired
private Demo1 demmo2;
@Test
public void test() {
System.out.println(demo1 ==demmo2);
}
}
测试输出:
构造函数.....com.bean.Demo1@107227e
构造函数.....com.bean.Demo1@7b636c
false