Spring注解 - 生命周期、属性赋值、自动装配

一、Bean的生命周期

流程

Bean创建 —— 初始化 —— 销毁

创建:

  • 单实例:在容器启动时创建对象
  • 多实例:每次调用时创建对象

初始化:

  • 都是在对象创建完成后,调用初始化方法

销毁:

  • 单实例:容器关闭时,调用销毁方法
  • 多实例:容器不会管理这个bean,只能手动调用销毁方法

实现方式

  1. 在 @Bean 注解上指定初始化(initMethod)、销毁方法(destroyMethod)

    @Bean(initMethod = "init", destroyMethod = "destroy")
    public Car car(){
        return new Car();
    }
  2. 让Bean实现 InitializingBeanDisposableBean 接口,重写它们的方法
    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...");
        }
    }
  3. 使用 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...");
        }
    }
  4. 实现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

时间: 2024-10-19 23:33:13

Spring注解 - 生命周期、属性赋值、自动装配的相关文章

Spring - bean的autowire属性(自动装配)

当我们要往一个bean的某个属性里注入另外一个bean,我们会使用<property> + <ref/>标签的形式.但是对于大型项目,假设有一个bean A被多个bean引用注入,如果A的id因为某种原因修改了,那么所有引用了A的bean的<ref/>标签内容都得修改,这时候如果使用autowire="byType",那么引用了A的bean就完全不用修改了.autowire到底都什么用?我们继续往下看. autowire的用法: <bean i

Spring注解驱动开发--属性赋值

前言 在实际开发当中,Spring中bean的属性直接赋值用的不是太多,整理这方面的资料,做一个小结,以备后续更深入的学习. 通过配置文件的方式 以配置文件的方式启动spring容器时,可以使用property标签的value给bean的属性赋值,赋值的形式有以下几种: <--通过context:property-placeholder将properties文件中的值加载的环境变量中(properties中的属性值最终是以环境变量的形式存储的)><context:property-pla

Spring点滴四:Spring Bean生命周期

Spring Bean 生命周期示意图: 了解Spring的生命周期非常重要,我们可以利用Spring机制来定制Bean的实例化过程. --------------------------------------------------------------------------------------------------------------------------------------------------- spring-service.xml: <?xml version=

spring框架学习(四)自动装配

spring框架学习(四)自动装配 set注入和构造注入有时在做配置时比较麻烦.所以框架为了提高开发效率,提供自动装配功能,简化配置.Spring框架式默认不支持自动装配的,要想使用自动装配需要修改spring配置文件中<bean>标签的autowire属性 自动装配属性有6个值可选,分别代表不同的含义. 1,byName 从Spring环境中获取目标对象时,目标对象中的属性会根据名称在整个Spring环境中查找<bean>标签的id属性值.如果有相同的,那么获取这个对象,实现关联

Spring的IOC容器—Bean的自动装配

我们对XML配置文件装配Bean的方式都很熟悉了,但是随着业务的复杂性,我们可能编写越来越复杂的XM配置. Spring提供了4种类型的自动装配的方式,帮助我们减少XML的配置数量.如下: byName:根据与bean的属性具有相同名字(或者ID)的其他bean进行注入 byType:   根据与bean的属性具有相同类型的其他bean进行注入 constructor:根据与bean的构造函数参数有相同类型的bean进行注入 autodetect :  首先尝试使用constructor进行注入

Spring4-自动装配Beans-按属性名称自动装配

1.创建Maven项目,项目名称springdemo15,如图所示 2.配置Maven,修改项目中的pom.xml文件,修改内容如下 <project xmlns="http://maven.apache.org/POM/4.0.0"  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0

Spring的IOC、Spring对象初始化bean时机、Spring容器生命周期

IOC指的是控制反转,把对象的创建.初始化.销毁等工作都交给Spring容器.由spring容器来控制对象的生命周期. Spring对象初始化bean时机: 在默认情况下,只要在Spring容器中配置了一个bean,容器在启动时就会实例化该bean,单例模式. 如果在Spring配制文件时设置懒加载模式(lazy-init="true"),在getBean时才会实例化对象. 如果scope="prototype"时,无论lazy-init的值是什么都只会在使用时才会

Spring 框架基础(02):Bean的生命周期,作用域,装配总结

本文源码:GitHub·点这里 || GitEE·点这里 一.装配方式 Bean的概念:Spring框架管理的应用程序中,由Spring容器负责创建,装配,设置属性,进而管理整个生命周期的对象,称为Bean对象. 1.XML格式装配 Spring最传统的Bean的管理方式. 配置方式 <bean id="userInfo" class="com.spring.mvc.entity.UserInfo"> <property name="na

Spring-IOC:Bean的作用域、生命周期、XML的装配、注解注入、@Autowired

8. 使用注解开发 在spring4之后,要使用注解开发,必须要保证aop的包导入了. 使用注解需要导入context约束,增加注解的支持! <!--指定要扫描的包,这个包下的注解会生效--> <context:component-scan base-package="com.kuang.pojo"/> bean 属性如何注入 //等价于<bean id="user" class="com.kuang.pojo.User&qu