目录
1.2.2@Component @PsotConstruct @PreDestroy 管理生命周期
1.2.3@Bean InltMethod destroyMethod 管理生命周期
1.Spring Bean管理
spring为了适合各种应用软件,提供了丰富的对象管理策略,我们可以根据软件中的实际业务场景选择适合的策略。
1.1Bean的作用域(Scope)
应用软件中的对象有着不同的生存范围,有的始终存在,而有的则作用范围非常短。
Spring针对对象的不同作用范围设计了Bean作用域,常用的有两个
- singleton(单例):指在一个应用软件运行期间某个类型的对象始终只有一个对象。即Spring中当一个对象作用域是单例的时候,任何时候Spring IOC容器中获得的对象都是同一个。
- prototype(原型):指应用软件执行期间有多个同类型的对象存在。即当Spring容器中一个对象作用域是原型时候,每次从SpringIOC容器获取的对象都是新对象。
注意:Spring中默认情况下Bean组件作用域是单例。
测试案例:
1.singleton
package com.jt.bean;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
@Component
@Scope("sinleton") //括号后面不写也可以,默认是sinleton 单例
public class BeanDemo {
@Override
public String toString() {
return "世界真美好!";
}
}
package com.jt.config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan(basePackages = "com.jt.bean")
public class Config {
}
package com.jt.test;
import com.jt.bean.BeanDemo;
import com.jt.config.Config;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import java.io.Serializable;
public class demo01 implements Serializable {
AnnotationConfigApplicationContext context;
@Before
public void before(){
context = new AnnotationConfigApplicationContext(Config.class);
}
@After
public void after(){
context.close();
}
//singleton 单例测试
@Test
public void testDemo(){
BeanDemo demoDemo = context.getBean("beanDemo", BeanDemo.class);
BeanDemo beanDemo2 = context.getBean("beanDemo", BeanDemo.class);
//== 比较的是两个对象的地址值
System.out.println(demoDemo == beanDemo2); //运行结果 ture
}
2.prototype
package com.jt.bean;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
@Component
@Scope("prototype")
public class BeanDemo {
@Override
public String toString() {
return "世界真美好!";
}
}
package com.jt.config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan(basePackages = "com.jt.bean")
public class Config {
}
package com.jt.test;
import com.jt.bean.BeanDemo;
import com.jt.config.Config;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import java.io.Serializable;
public class demo01 implements Serializable {
AnnotationConfigApplicationContext context;
@Before
public void before(){
context = new AnnotationConfigApplicationContext(Config.class);
}
@After
public void after(){
context.close();
}
//测试 prototype 原型
@Test
public void testDemo(){
BeanDemo demoDemo = context.getBean("beanDemo", BeanDemo.class);
BeanDemo beanDemo2 = context.getBean("beanDemo", BeanDemo.class);
//== 比较的是两个对象的地址值
System.out.println(demoDemo == beanDemo2); //false
}
}
1.2对生命周期管理
1.2.1描述
软件中对象都存在从创建到使用最后销毁的过程,这个过程称为对象的生命周期(Life cycle)。
主动控制的时候,对象的创建,使用,销毁都是有我们自己主动完成的,即主动控制对象的生命周期,这时候我们可以在对象创建的时候可以进行初始化,在销毁对象时候关闭资源。例如:写文件之前需要先将文件打开,然后写文件,最后将文件关闭。
当使用了Spring IOC后,这一切都可以交给spring去做,SpringIOC提供了两种对象生命周期管理功能。
1.2.2@Component @PsotConstruct @PreDestroy 管理生命周期
使用@Component注解管理Bean组件时候,使用@PostConstruct 和 @PreDestroy注解管理对象的声明周期方法
1)注意:这两个注解不是Spring注解,是java提供的拓展注解,需要导入javax.annotation 包
2)@PostContruct注解标注的方法在创建对象以后执行
3)@PreDestroy注解标注的方法在容器关闭对象时执行
案例:
package com.jt.bean;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import java.io.IOException;
import java.io.PrintWriter;
@Component
public class FileLogger {
public PrintWriter out;
@PostConstruct
public void open()throws IOException {
out = new PrintWriter("Demo.txt");
System.out.println("文件打开成功!");
}
@PreDestroy
public void close(){
out.close();
System.out.println("文件关闭成功");
}
}
@Test
public void testFileLogger() {
FileLogger fileLogger = context.getBean("fileLogger", FileLogger.class);
fileLogger.out.println("hahaha");
fileLogger.out.println("我爱中国");
}
结果:
注意:
关闭文件Demo.txt是在关闭容器时候输出的,如果没有关闭容器,就没有这个输出
1.2.3@Bean InltMethod destroyMethod 管理生命周期
使用@Bean注解管理Bean组件时候,在其InItMethod和destroyMethod属性上标注生命周期管理方法名
1)InItMethod属性引用的方法在创建对象以后执行
2)destroyMethod属性引用的方法在容器关闭对象时执行
案例:
package com.jt.bean;
import java.io.IOException;
import java.io.PrintWriter;
public class FilerLogger2 {
public PrintWriter out;
public void open()throws IOException {
out=new PrintWriter("Demo2.txt");
System.out.println("文件打开成功");
}
public void close()throws IOException {
System.out.println("hhahh");
out.close();
System.out.println("文件关闭成功!");
}
}
package com.jt.config;
import com.jt.bean.FilerLogger2;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
//import org.springframework.context.annotation.Scope;
@Configuration
public class ConfigFilerLogger2 {
@Bean(initMethod = "open",destroyMethod = "close")
//@Scope("prototype")
public FilerLogger2 fileLogger2Bean(){
return new FilerLogger2();
}
}
package com.jt.test;
import com.jt.bean.FilerLogger2;
import com.jt.config.ConfigFilerLogger2;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class Demo02 {
AnnotationConfigApplicationContext applicationContext;
//创建容器
@Before
public void before(){
applicationContext = new AnnotationConfigApplicationContext(ConfigFilerLogger2.class);
}
//关闭容器
@After
public void after(){
System.out.println("关闭容器");
applicationContext.close();
}
@Test
public void testDemo02(){
FilerLogger2 filerLogger2 = applicationContext.getBean("fileLogger2Bean", FilerLogger2.class);
filerLogger2.out.println("hhahh");
}
}
测试结果:
注意:
@Scope(“prototype”)时候,每次使用都会创建一个对象,Spring为了避免内存泄漏,不会缓存对象的引用,所以Spring关闭时候就无法处理对象的销魂方法了!
1.3懒惰初始化
为了提高开发效率,Spring默认情况下在启动时候讲Bean立即实例化,这样在用的时候就可以立刻使用,但是这样子也有缺点,如果某个Bean很少使用,甚至不使用,但是却被创建出来了,就会造成资源浪费。
为了解决这个情况,Spring提供了“懒惰初始化”,避免这种情况发生。
Spring中利用@Lazy注解开启懒汉初始化,开启懒惰初始化后如果不使用Bean组件,将不会初始化对象。
1.3.1@Lazy 和 @Component 一起使用
案例:
package com.jt.bean;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;
@Component
@Lazy
public class Person {
public Person(){
System.out.println("创建成功!");
}
@Override
public String toString() {
return "hahh";
}
}
package com.jt.config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan(basePackages = "com.jt.bean")
public class PensonConfig {
}
package com.jt.test;
import com.jt.bean.Person;
import com.jt.config.PensonConfig;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class PersonTest {
AnnotationConfigApplicationContext cgx;
//创建spring容器
@Before
public void brfore(){
cgx = new AnnotationConfigApplicationContext(PensonConfig.class);
System.out.println("spring容器创建成功!");
}
@After
public void after(){
cgx.close();
System.out.println("spring容器关闭成功");
}
@Test
public void testPerson(){
// Person person = cgx.getBean("person", Person.class);
// System.out.println(person);
System.out.println("ok");
}
}
输出结果:
1.3.2 @Lazy 和 @Bean 一起使用
@Lazy 和 @Component一起使用的效果相同,可根据业务的需求来自己定。
1.4@import 导入配置
Spring提供了多配置类功能,利用@import注解可以同时使用多个配置类
在项目的开发中都是分模块进行的,如果两个人同时用一个Config作为配置,则会出现很多不必要的麻烦,降低开发效率。
如果两个人分别写自己的配置文件,利用@import导入到主配置文件中,使配置文件一起作用,这样就可以解决以上问题。