引言
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接口 | 目标资源 |
---|---|
BeanNameAware | ioc容器中配置的实例的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的生命周期有时候可以达到事半功倍的效果。