目录
1.Bean的作用域
1.1案例
现有一个公共Bean
@Component
public class UserBean {
@Bean
public User user1() {
User user = new User();
user.setId(1);
user.setName("张三");
user.setAge(18);
return user;
}
}
用户一进行了修改的操作
@Controller
public class UserControllerA {
@Autowired
private User user1;
public User getUser1() {
User user = user1;
System.out.println("用户1修改之前: " + user1);
user.setName("王五");
return user;
}
}
用户2进行了读取操作
@Controller
public class UserControllerB {
@Autowired
private User user1;
public User getUser1() {
User user = user1;
return user;
}
}
打印用户一和用户二公共Bean值
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
UserControllerA userControllerA = context.getBean("userControllerA",UserControllerA.class);
User user = userControllerA.getUser1();
System.out.println("用户1修改之后: " + user);
UserControllerB userControllerB = context.getBean("userControllerB",UserControllerB.class);
User user1 = userControllerB.getUser1();
System.out.println("用户2读取到的: " + user1);
}
原因:Spring中Bean的作用域默认是singleton单例模式,所有人使用的都是同一个对象
1.2.作用域的定义
之前所说的作用域,是在程序中定义的某个变量的某个区域就叫做作用域,这里的Bean作用域不同
Bean的作用域指:Bean在Spring整个框架中的某中行为模式
例如:singleton单例作用域,就表示Bean在整个Spring中只有一份,它是全局共享的,那么当其他人修改了这个值之后,那么另一个人读取到的就是被修改的值
1.3.Bean的6种作用域
Spring容器在初始化一个Bean的示例时,同时会指定该实例的作用域
1)singleton:单例作用域
2)prototype:原型作用域(多例作用域)
3)request:请求作用域
4)session:回话作用域
5)application:全局作用域
6)websocket:HTTPWebsocket作用域
(3~~6这四种是Spring MVC中值)
1.4.如何设置Bean的作用域
@Scope既可以用于方法注解,也可以用于类注解
① @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
② @Scope(“prototype”)
(两种都可以)
@Component
public class UserBean {
@Bean
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public User user1() {
User user = new User();
user.setId(1);
user.setName("张三");
user.setAge(18);
return user;
}
}
注意:如果是@Bean + @Scope , 这里的@Scope 就不能写成类注解的方式了
2.Bean的生命周期
2.1Bean的执行流程
1)启动Spring容器
2)加载Spring配置文件
3)加载Spring配置文件中Bean,或者根据配置文件中的组件根路径,进行Bean对象的扫描(扫描@Controller...)
4)Bean注册到Spring中
5)执行完毕,执行销毁操作
2.2Bean生命周期
1)实例化Bean(为Bean分配内存空间)
2)设置属性(Bean进行初始化注入)
3)Bean初始化
① 各种通知 (
xxxAware
)
② 执行初始化前置方法BeanPostProcessor
③ 执行@PostConstruct
初始化方法
④ 执行 init-mehtod
初始化方法
⑤ 执行初始化后置方法BeanPostProcessor
4)使用Bean
5)销毁Bean
① 执行销毁前方法
@PreDestory
② 如果有接口DisposableBean
, 执行实现方法
③ 执行销毁前的方法destory-method
2.3生命周期代码
package com.wwzz.util;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
@Component
public class BeanLifeComponent implements BeanNameAware {
@Override
public void setBeanName(String s) {
System.out.println("执行通知: BeanNameAware " + s);
}
@PostConstruct
public void postConstruct(){
System.out.println("执行 @PostConstruct");
}
public void init() {
System.out.println("执行 init-method");
}
@PreDestroy
public void preDestroy(){
System.out.println("执行 @PreDestroy");
}
public void destroy() {
System.out.println("执行 destroy");
}
}
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:content="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<!-- 配置 Spring 扫描的根路径(此根路径下的所有 Spring 存对象的注解才能生效) -->
<content:component-scan base-package="com.wwzz"></content:component-scan>
<beans>
<bean id="beanLifeComponent" class="com.wwzz.util.BeanLifeComponent" init-method="init" destroy-method="destroy"></bean>
</beans>
</beans>
测试代码:
public static void main(String[] args) {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
BeanLifeComponent beanLifeComponent = context.getBean("beanLifeComponent",BeanLifeComponent.class);
context.destroy();
}
结果: