Spring中Bean的创建和生命周期

引言

Spring是最常用的Java框架之一,这篇文章笔者总结一下Spring中Bean的创建以及Bean的生命周期

环境准备

在开始前,需要引入Spring相关jar包,在maven中增加如下配置:

org.springframework spring-context 5.2.19.RELEASE 其他版本可在https://mvnrepository.com/artifact/org.springframework/spring-context查找

创建Bean的方式

使用xml创建

下面这段配置可以为容器中增加一个Person类型的bean(当然前提是我们已经定义了一个Person类)

<?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">

    <bean id = "person" class = "com.jolan.bean.Person">
        <property name="name" value="wql"></property>
        <property name="age" value="18"></property>
    </bean>
</beans>

使用@Bean注解创建

也可以使用注解的方式为Spring容器中添加bean。如下面代码段所示为容器中注入一个id为person的Bean

@Configuration //表示这是一个配置类
public class MainConfig {
    //给容器中注册一个bean;类型为返回值的类型;id默认是方法名
    @Bean
    public Person person(){
        return new Person("zhangsan", 20);
    }
}

如果要修改bean的id,只需要在@Bean中指定即可,如@Bean(“zhangsan”)

使用@Import创建

如果上面的看起来还有点麻烦,我们还可以用更快速的方式——@Import

@Configuration
@Import(Person.class)//导入的bean的id默认是全类名
public class MainConfig {
    //其他操作。。。
}
@Import也支持一次导入多个组件,使用逗号分隔即可,比如有一个动物类Animal
@Configuration
@Import({Person.class, Animal.class})
public class MainConfig {
    //其他操作。。。
}

ImportSelector配合@Import

如果我们一次性需要创建的bean比较多,还可以使用ImportSelector来导入一个数组,首先需要一个实现ImportSelector的类,然后通过@Import直接导入

public class JolanImportSelector implements ImportSelector {
    //自定义逻辑需要返回的bean数组,需要全类名
    public String[] selectImports(AnnotationMetadata annotationMetadata) {
        return new String[]{"com.jolan.bean.Person", "com.jolan.bean.Animal"};
    }
}

@Import(JolanImportSelector.class})
public class MainConfig {
    //其他操作
}

ImportBeanDefinitionRegistrar配合@Import

这种方式个人用的比较少,但是却比较灵活,可以根据情况来创建需要的bean。举个例子:当Spring容器中存在Person和Animal时,我们就创建一个名称为pet的宠物bean,否则不创建

public class JolanImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
   
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        boolean hasPerson = registry.containsBeanDefinition("com.jolan.bean.Person");
        boolean hasAnimal = registry.containsBeanDefinition("com.jolan.bean.Animal");
        if(hasPerson && hasAnimal){
            //创建宠物bean
            RootBeanDefinition rootBeanDefinition = new RootBeanDefinition(Pet.class);
            registry.registerBeanDefinition("pet", rootBeanDefinition);
        }
    }
}

@Import(JolanImportBeanDefinitionRegistrar.class)
public class MainConfig {
    
}

使用FactoryBean创建

我们可以通过FactoryBean比较透明的创建一个Bean。FactoryBean规定了需要返回的bean的实例、bean的类型以及是否单例:

package org.springframework.beans.factory;

public interface FactoryBean <T> {
    java.lang.String OBJECT_TYPE_ATTRIBUTE = "factoryBeanObjectType";

    @org.springframework.lang.Nullable
    T getObject() throws java.lang.Exception;

    @org.springframework.lang.Nullable
    java.lang.Class<?> getObjectType();

    default boolean isSingleton() { /* compiled code */ }
}

实现FactoryBean即可:

/**
 * 
 */
public class PersonFactoryBean implements FactoryBean<Person> {
    
    public Person getObject() throws Exception {
        return new Person();
    }

    public Class<?> getObjectType() {
        return Person.class;
    }
    
    public boolean isSingleton() {
        return true;
    }
}

最后将PersonFactoryBean注入到容器中

@Bean
public PersonFactoryBean personFactoryBean(){
    return new PersonFactoryBean();
}

Bean的生命周期

完整的执行过程

下面我们用一个完整的示例来展示Person这个Bean从创建到销毁的整个过程

创建Person类

package com.jolan.lifecycle;


import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;

public class Person implements BeanFactoryAware, BeanNameAware,
        InitializingBean, DisposableBean {

    private String name;
    private int age ;

    private BeanFactory beanFactory;
    private String beanName;

    public Person(String name, int age) {
        System.out.println("Person的构造方法执行。。。");
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        System.out.println("注入name属性。。。");
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        System.out.println("注入age属性。。。");
        this.age = age;
    }

    public BeanFactory getBeanFactory() {
        return beanFactory;
    }

    // BeanFactoryAware接口方法
    public void setBeanFactory(BeanFactory arg0) throws BeansException {
        System.out.println("调用BeanFactoryAware的setBeanFactory方法。。。");
        this.beanFactory = arg0;
    }

    // BeanNameAware接口方法
    public void setBeanName(String arg0) {
        System.out.println("调用BeanNameAware的setBeanName方法。。。");
        this.beanName = arg0;
    }

    // InitializingBean接口方法
    public void afterPropertiesSet() throws Exception {
        System.out.println("调用InitializingBean的afterPropertiesSet方法。。。");
    }

    // DiposibleBean接口方法
    public void destroy() throws Exception {
        System.out.println("调用DiposibleBean的destory方法。。。");
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

    public void init_method(){
        System.out.println("调用自定义的init-method。。。");
    }

    public void destroy_method(){
        System.out.println("调用自定义的destroy-method。。。");
    }
}

创建BeanFactoryProcessor实现类

package com.jolan.lifecycle;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.stereotype.Component;

@Component
public class JolanBeanFactoryPostProcessor implements BeanFactoryPostProcessor {

    public JolanBeanFactoryPostProcessor() {
        super();
        System.out.println("BeanFactoryPostProcessor实现类的构造器。。。");
    }

    public void postProcessBeanFactory(ConfigurableListableBeanFactory arg0)
            throws BeansException {
        System.out.println("调用BeanFactoryPostProcessor的postProcessBeanFactory方法。。。");
        BeanDefinition bd = arg0.getBeanDefinition("person");
        bd.getPropertyValues().addPropertyValue("age", 20);
    }

}

创建InstantiationAwareBeanPostProcessor实现类

package com.jolan.lifecycle;

import java.beans.PropertyDescriptor;
import org.springframework.beans.BeansException;
import org.springframework.beans.PropertyValues;
import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessorAdapter;
import org.springframework.stereotype.Component;

@Component
public class JolanInstantiationAwareBeanPostProcessor extends
        InstantiationAwareBeanPostProcessorAdapter {

    public JolanInstantiationAwareBeanPostProcessor() {
        super();
        System.out.println("InstantiationAwareBeanPostProcessorAdapter实现类构造器。。。");
    }

  
    @Override
    public Object postProcessBeforeInstantiation(Class beanClass,
            String beanName) throws BeansException {
        System.out.println("调用InstantiationAwareBeanPostProcessor的postProcessBeforeInstantiation方法。。。");
        return null;
    }

    
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName)
            throws BeansException {
        System.out.println("调用InstantiationAwareBeanPostProcessor的postProcessAfterInitialization方法。。。");
        return bean;
    }

    
    @Override
    public PropertyValues postProcessPropertyValues(PropertyValues pvs,
            PropertyDescriptor[] pds, Object bean, String beanName)
            throws BeansException {
        System.out.println("调用InstantiationAwareBeanPostProcessor的postProcessPropertyValues方法。。。");
        return pvs;
    }
}

创建BeanPostProcessor实现类

package com.jolan.lifecycle;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.stereotype.Component;

@Component
public class JolanBeanPostProcessor implements BeanPostProcessor {


    public JolanBeanPostProcessor() {
        super();
        System.out.println("BeanPostProcessor实现类的构造器。。。");
    }


    public Object postProcessAfterInitialization(Object arg0, String arg1) throws BeansException {
        System.out.println("调用BeanPostProcessor的postProcessAfterInitialization方法对属性进行更改。。。");
        return arg0;
    }


    public Object postProcessBeforeInitialization(Object arg0, String arg1) throws BeansException {
        System.out.println("调用BeanPostProcessor接口的方法postProcessBeforeInitialization对属性进行更改。。。");
        return arg0;
    }
}

创建配置类

package com.jolan.config;


import com.jolan.lifecycle.Person;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;


@Configuration
@ComponentScan("com.jolan.lifecycle")
public class MainPersonLifeCycle {
    @Bean(initMethod = "init_method", destroyMethod = "destroy_method")
    public Person person(){
        return new Person("wql", 18);
    }
}

创建测试类

package com.jolan.test;


import com.jolan.config.MainConfigLifeCycle;
import com.jolan.config.MainPersonLifeCycle;
import com.jolan.lifecycle.Person;
import org.junit.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;


public class PersonLifecycleTest {
    @Test
    public void test01(){
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainPersonLifeCycle.class);


        Person person = (Person)applicationContext.getBean("person");
        System.out.println(person);
        //关闭容器
        applicationContext.close();
    }
}

运行结果

BeanFactoryPostProcessor实现类的构造器。。。
调用BeanFactoryPostProcessor的postProcessBeanFactory方法。。。
BeanPostProcessor实现类的构造器。。。
InstantiationAwareBeanPostProcessorAdapter实现类构造器。。。
调用InstantiationAwareBeanPostProcessor的postProcessBeforeInstantiation方法。。。
调用InstantiationAwareBeanPostProcessor的postProcessPropertyValues方法。。。
调用BeanPostProcessor接口的方法postProcessBeforeInitialization对属性进行更改。。。
调用BeanPostProcessor的postProcessAfterInitialization方法对属性进行更改。。。
调用InstantiationAwareBeanPostProcessor的postProcessAfterInitialization方法。。。
调用InstantiationAwareBeanPostProcessor的postProcessBeforeInstantiation方法。。。
Person的构造方法执行。。。
调用InstantiationAwareBeanPostProcessor的postProcessPropertyValues方法。。。
注入age属性。。。
调用BeanNameAware的setBeanName方法。。。
调用BeanFactoryAware的setBeanFactory方法。。。
调用BeanPostProcessor接口的方法postProcessBeforeInitialization对属性进行更改。。。
调用InitializingBean的afterPropertiesSet方法。。。
调用自定义的init-method。。。
调用BeanPostProcessor的postProcessAfterInitialization方法对属性进行更改。。。
调用InstantiationAwareBeanPostProcessor的postProcessAfterInitialization方法。。。
Person{name='wql', age=20}
调用DiposibleBean的destory方法。。。
调用自定义的destory-method。。。

根据测试结果,我们已经对Spring容器中Bean的生命周期有了大致的认识,下面对每个过程做一个简短的介绍。

自定义bean初始化和析构

InitializingBean和DisposableBean

可以直接实现InitializingBean和DisposableBean接口中的afterPropertiesSet和destory方法,Spring容器会自动在合适的时机调用,前提是对象是受Spring容器管理的,如下面代码片段中需要使用@Component注解(其他方式也可以,见第一部分“创建Bean的方式”)。

import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Component;
@Component
public class Person implements InitializingBean, DisposableBean {
    public void destroy() throws Exception {
        
    }
    public void afterPropertiesSet() throws Exception {

    }
}

init-method和destory-metohd

Spring容器还支持通过指定init-method和destory-method来指定初始化和析构方法。根据上一部分的描述可知,init-method的执行时机在InitializingBean接口的afterPropertiesSet方法之后,destroy-method执行时机在DisposableBean接口的destory方法之后

@Bean(initMethod = "init_method", destroyMethod = "destroy_method")
public Person person(){
    return new Person();
}

public class Person {

    public void init_method() {
        
    }


    public void destroy_method throws Exception {

    }
}   

@PostConstruct和@PreDestroy

在Spring和2.5或更高的版本中可以使用@PostConstruct和@PreDestory来注解初始化和析构回调方法

import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
@Component
public class Person {
    @PreDestroy
    public void destroy() throws Exception {
    }
    @PostConstruct
    public void afterPropertiesSet() throws Exception {
    }
}

Bean Aware接口

Spring中的常见Aware接口

Aware接口目标资源
BeanNameAwareioc容器中配置的实例的Bean名称
BeanFactoryAware当前的Bean工厂
ApplicationContextAware当前上下文
MessageSourceAware消息资源
ApplicationEventPublisherAware应用事件发布者
ResourceLoaderAware资源装载器

我们可以通过实现各种各样的Aware接口非常方便的获取Spring的相关资源,如下面代码片段中试图修改Bean的名称:

import org.springframework.beans.factory.BeanNameAware;
import org.springframework.stereotype.Component;


@Component
public class Person implements BeanNameAware {
  
    public void setBeanName(String s) {  

 }
}

BeanFactoryProcessor接口

BeanFactoryPostProcessor的执行时机是在所有的bean定义已经保存加载到BeanFactory,但是Bean的实例还没有创建

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.stereotype.Component;

@Component
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
    public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
  }
}

BeanPostProcessor接口

Bean处理器的基本要求是实现BeanPostProcessor接口,Spring也为我们提供了一些已经实现了BeanPostProcessor的子接口如InstantiationAwareBeanPostProcessorAdapter(见上文中的“完成的执行过程”)

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.stereotype.Component;


@Component
public class Person implements BeanPostProcessor {
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        return bean;
    }


    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        return bean;
    }
}

总结

从Bean初始化,到Bean销毁的过程,Spring为我们提供了非常多的方法来做一些个性化的设置,熟练的掌握Spring的生命周期有时候可以达到事半功倍的效果。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值