一, Bean 的生命周期
流程
Bean 创建 -- 初始化 -- 销毁
创建:
单实例: 在容器启动时创建对象
多实例: 每次调用时创建对象
初始化:
都是在对象创建完成后, 调用初始化方法
销毁:
单实例: 容器关闭时, 调用销毁方法
多实例: 容器不会管理这个 bean, 只能手动调用销毁方法
实现方式
在 @Bean 注解上指定初始化 (initMethod), 销毁方法 (destroyMethod)
- @Bean(initMethod = "init", destroyMethod = "destroy")
- public Car car(){
- return new Car();
- }
让 Bean 实现 InitializingBean 和 DisposableBean 接口, 重写它们的方法
- public class Cat implements InitializingBean, DisposableBean {
- public Cat() {
- System.out.println("Cat...Construct...");
- }
- @Override
- public void afterPropertiesSet() throws Exception {
- System.out.println("Cat...init...");
- }
- @Override
- public void destroy() throws Exception {
- System.out.println("Cat...destroy...");
- }
- }
使用 JSR250 中的 @PostConstruct 和 @PreDestroy 注解标注初始化, 销毁方法
- public class Dog {
- public Dog() {
- System.out.println("Dog...Construct...");
- }
- @PostConstruct
- public void init(){
- System.out.println("Dog...init...");
- }
- @PreDestroy
- public void destroy(){
- System.out.println("Dog...destroy...");
- }
- }
实现 BeanPostProcessor 接口, 重写
- postProcessBeforeInitialization(在初始化之前工作)
- postProcessAfterInitialization(在初始化之后工作)
- public class MyBeanPostProcessor implements BeanPostProcessor {
- @Override
- public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
- System.out.println("postProcessBeforeInitialization" + beanName);
- return bean;
- }
- @Override
- public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
- System.out.println("postProcessAfterInitialization" + beanName);
- return bean;
- }
- }
二, 属性赋值相关注解
@Value
作用:
添加在字段上, 用于给属性赋值
属性:
value: 指定要传入的值
用法:
- public class Person {
- @Value("张三") // 普通方式赋值
- private String name;
- @Value("#{20 - 1}") // 使用 SpEL 表达式
- private Integer age;
- @Value("${person.nickName}") // 使用 ${} 读取配置文件内容
- private String nickName;
- // 省略 getter setter toString 方法
- }
上述第三种方式显然是不能读取到的, 我们需要配置一下配置文件的位置, 使用到下面这个注解
@PropertySource
作用:
读取指定的外部配置文件, 将 K/V 键值对保存到运行的环境变量中, 用 ${} 来获取
属性:
name: 给属性源指定一个名称
value: 要加载的配置文件的路径, 可以指定多个
ignoreResourceNotFound: 是否忽略资源未找到的情况, 默认 false
encoding: 给定资源的特定字符编码, 例如 "UTF-8"
factory: 指定一个自定义属性源工厂, 默认使用 PropertySourceFactory
用法:
在 resources 目录下创建一个 properties 文件, 内容如下
person.nickName = 小张
然后在配置类上标注 @PropertySource("classpath:person.properties") 即可
可以直接在 @Value 注解中获取, 也可以通过 IoC 容器对象获取
- ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfiguration4.class);
- String nickName = context.getEnvironment().getProperty("person.nickName");
- System.out.println(nickName);
三, 自动装配相关注解
Spring 利用依赖注入 (DI), 完成对 IoC 容器中各个组件的依赖关系赋值
@Autowired
默认按照类型去容器中寻找对应的组件, 如果只有一个就赋值
如果找到多个相同类型的组件, 再按照属性名寻找
有一个 required 属性, 默认是 true;
可以写在构造器, 方法, 参数, 属性上
@Qualifier
一般配合 @Autowired 使用, 指定需要装配的组件的 id,@Autowired 就直接按照 id 注入.
如果 id 对应的组件不存在, 并且没有指定 required = false, 则会报错
@Primary
让 Spring 进行自动装配的时候, 首先选择标注了 @Primary 的组件
如果已经使用 @Qualifier 指明了要装配的组件, 则不生效
不常用的两个自动注入注解:
@Resource(JSR250)
java 规范里的注解, 和 @Autowired 一样可以实现自动装配
默认使用变量名作为 id, 不能配合 @Qualifier @Primary 使用
@Inject(JSR330)
和 @Autowired 一样, 但是没有 required 属性, 需要导入 javax.inject 的 jar 包
- <dependency>
- <groupId>javax.inject</groupId>
- <artifactId>javax.inject</artifactId>
- <version>1</version>
- </dependency>
- @Profile
指定组件在哪个环境下才被注册到容器中, 不指定则在哪个环境都注册
可以指定多个环境, default 为默认环境
可以写在配置类上
还可以用代码的方式指定环境
- AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(SpringConfiguration5.class);
- applicationContext.getEnvironment().setActiveProfiles("prod");
四, 使用 Spring 容器底层组件
对于自定义组件, 如果想要使用 Spring 容器底层组件, 可以实现 Aware 接口的子接口 (xxxAware), 如下图所示
- @Component
- public class TestAware implements ApplicationContextAware {
- private ApplicationContext applicationContext;
- @Override
- public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
- System.out.println("传入的 IOC 容器:" + applicationContext);
- this.applicationContext = applicationContext;
- }
- }
这些 xxxAware 的功能都是通过 ApplicationContextAwareProcessor 来处理的
- class ApplicationContextAwareProcessor implements BeanPostProcessor {
- private final ConfigurableApplicationContext applicationContext;
- private final StringValueResolver embeddedValueResolver;
- /**
- * Create a new ApplicationContextAwareProcessor for the given context.
- */
- public ApplicationContextAwareProcessor(ConfigurableApplicationContext applicationContext) {
- this.applicationContext = applicationContext;
- this.embeddedValueResolver = new EmbeddedValueResolver(applicationContext.getBeanFactory());
- }
- @Override
- @Nullable
- public Object postProcessBeforeInitialization(final Object bean, String beanName) throws BeansException {
- AccessControlContext acc = null;
- if (System.getSecurityManager() != null &&
- (bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware ||
- bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware ||
- bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware)) {
- acc = this.applicationContext.getBeanFactory().getAccessControlContext();
- }
- if (acc != null) {
- AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
- invokeAwareInterfaces(bean);
- return null;
- }, acc);
- }
- else {
- invokeAwareInterfaces(bean);
- }
- return bean;
- }
- // 根据传入 bean 的类型来为 bean 注入不同的组件
- private void invokeAwareInterfaces(Object bean) {
- if (bean instanceof Aware) {
- if (bean instanceof EnvironmentAware) {
- ((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment());
- }
- if (bean instanceof EmbeddedValueResolverAware) {
- ((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(this.embeddedValueResolver);
- }
- if (bean instanceof ResourceLoaderAware) {
- ((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext);
- }
- if (bean instanceof ApplicationEventPublisherAware) {
- ((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext);
- }
- if (bean instanceof MessageSourceAware) {
- ((MessageSourceAware) bean).setMessageSource(this.applicationContext);
- }
- if (bean instanceof ApplicationContextAware) {
- ((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
- }
- }
- }
- @Override
- public Object postProcessAfterInitialization(Object bean, String beanName) {
- return bean;
- }
- }
来源: https://www.cnblogs.com/songjilong/p/12519617.html