前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >被隔离了,聊一聊春(Spring)的生命周期

被隔离了,聊一聊春(Spring)的生命周期

作者头像
小四的技术之旅
发布2022-07-26 08:01:12
3270
发布2022-07-26 08:01:12
举报
文章被收录于专栏:小四的技术文章

码农在囧途

从北京回成都被隔离7天,今天是第二天,我是一个比较自由的人,如果让我宅在屋子里面,我真的会疯掉,我总是盯着窗外看,不由自主地想到钱钟书在《围城》里面说:"婚姻是一座围城,城外的人想进去,城里的人想出来,虽然我没有婚姻",不过以我目前被隔离的状态,我是能理解那种感受的,我看到身边不少的男性女性朋友步入婚姻后,有的幸福,有的是无比的痛苦,不过,你在选择的时候,就要想清楚你是否能承担这个选择给你带来的后果,任何事物都是这样,不论婚姻,学业,事业,爱情等,美好的事物可能会伴随不好的结果,同样,不好的开端同样可能会收获完美的结局,这一切都取决于我们怎么抉择,如果你喜欢城外,那么就呆在城外,你喜欢城里,那么就呆在城里!

前言

今天我们来分享一下Spring Bean的生命周期,Spring Bean的生命周期对于我们掌握Spring来说是很关键的,理解了Spring的生命周期,那么我们在开发的时候才能更好的利用Spring的功能,从而达到我们的目的!

Spring Bean的生命周期图

1.Bean元信息配置

此阶段主要配置bean的信息,bean的配置有xml,注解,properties,API BeanDefinition方式,我们主要用的是xml和注解,不过随着 springboot的发展,现在xml也不怎么用了,一般都是使用注解,不过这些方式最终都会通过解析,然后配置到BeanDefinition中,所以我们可以直接 通过原生API BeanDefinition来创建Bean,下面我们主要通过xml和注解来配置简单的Bean。

定义一个Bean

代码语言:javascript
复制
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
    private String username;
    private String idCard;
}

XML方式

构造注入
代码语言:javascript
复制
<bean id="user" class="com.steak.spring.beanbuild.User">
    <constructor-arg index="0" name="username" value="steak"/>
    <constructor-arg index="1" name="idCard" value="522425199812290589"/>
</bean>
set注入
代码语言:javascript
复制
<bean id="user" class="com.steak.spring.beanbuild.User">
    <property name="username" value="steak"/>
    <property name="idCard" value="522425199812290589"/>
</bean>

注解方式

使用@Configuration@Bean

代码语言:javascript
复制
@Configuration
public class UserConfig {

    @Bean
    public User user(){
        return new User("steak","123456");
    }
}

使用@Component@Service,@Controller等注解申明一个Bean

代码语言:javascript
复制
@Component
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
    private String username;
    private String idCard;
}

使用BeanDefinition直接配置一个Bean

使用BeanDefinitionBuilder建造者来构建一个Bean,并设置属性和其他一些信息,如作用域scope,懒加载lazyInit等,使用addPropertyValue来填充属性,构建完成之后使用DefaultListableBeanFactoryregisterBeanDefinition注册到Spring工厂。

代码语言:javascript
复制
public class BeanBuildTest {
    public static void main(String[] args) {
        //构建BeanDefinition
        BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.rootBeanDefinition(User.class.getName());
        beanDefinitionBuilder.addPropertyValue("username","steak");
        beanDefinitionBuilder.addPropertyValue("idCard","522425199812290045");
        AbstractBeanDefinition userBeanDefinition = beanDefinitionBuilder.getBeanDefinition();
        System.out.println(userBeanDefinition);

        //注册Bean
        DefaultListableBeanFactory defaultListableBeanFactory = new DefaultListableBeanFactory();
        defaultListableBeanFactory.registerBeanDefinition("user",userBeanDefinition);
        
        //获取Bean
        User user = defaultListableBeanFactory.getBean("user", User.class);
        System.out.println(user);
    }
}

2.Bean元信息解析阶段

第二阶段主要是解析Bean的元信息,这里我们主要来演示解析XML注解方式的Bean,

解析XML

使用XmlBeanDefinitionReader来对xml文件进行解析,loadBeanDefinitions加载spring配置文件,这个方法返回参数是一个整数, 代表Bean的个数,然后使用DefaultListableBeanFactorygetBeanDefinitionNames获取所有Bean,返回一个数组,我们再对其解析。

代码语言:javascript
复制
public class XmlBeanReaderTest {
    public static void main(String[] args) {
        DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
        XmlBeanDefinitionReader xmlBeanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
        xmlBeanDefinitionReader.loadBeanDefinitions("spring.xml");
        String[] beanDefinitionNames = beanFactory.getBeanDefinitionNames();
        for (String definitionName : beanDefinitionNames) {
            BeanDefinition beanDefinition = beanFactory.getBeanDefinition(definitionName);
            System.out.println(beanDefinition.getPropertyValues());
            System.out.println(definitionName);
        }
    }
}

解析注解

注解使用AnnotatedBeanDefinitionReader对Bean进行解析

代码语言:javascript
复制
public class AnnotationBeanReaderTest {
    public static void main(String[] args) {
        DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
        AnnotatedBeanDefinitionReader reader = new AnnotatedBeanDefinitionReader(beanFactory);
        reader.register(UserService.class);
        BeanDefinition beanDefinition = beanFactory.getBeanDefinition("userService");
        System.out.println(beanDefinition);
    }
}

3.将Bean注册到Spring容器中

解析完Bean以后,需要将Bean注册到Spring容器中,注册Bean有一个接口BeanDefinitionRegistry,它继承了AliasRegistry接口,可以看出它提供了设置别名 的一些操作,BeanDefinitionRegistry是一个接口,我们不能直接进行实例化,所以我们一般使用的是它的实现类DefaultListableBeanFactory

BeanDefinitionRegistry

代码语言:javascript
复制
public interface BeanDefinitionRegistry extends AliasRegistry {
    void registerBeanDefinition(String var1, BeanDefinition var2) throws BeanDefinitionStoreException;

    void removeBeanDefinition(String var1) throws NoSuchBeanDefinitionException;

    BeanDefinition getBeanDefinition(String var1) throws NoSuchBeanDefinitionException;

    boolean containsBeanDefinition(String var1);

    String[] getBeanDefinitionNames();

    int getBeanDefinitionCount();

    boolean isBeanNameInUse(String var1);
}

AliasRegistry

代码语言:javascript
复制
public interface AliasRegistry {
    //设置别名
    void registerAlias(String name, String alias);
    //移除别名
    void removeAlias(String alias);
    //是否是别名
    boolean isAlias(String name);
    //获取别名
    String[] getAliases(String name);
}

注册Bean

注册Bean需要使用一个BeanDefinitionBuilder建造者来建造一个BeanDefinition,上面已经说过,这里不赘述。建造完成以后再使用BeanDefinitionRegistry来注册Bean,使用registerBeanDefinition进行注册。 的

代码语言:javascript
复制
public class BeanRegister {
    public static void main(String[] args) {
        //构建BeanDefinition
        BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.rootBeanDefinition(User.class.getName());
        beanDefinitionBuilder.addPropertyValue("username","steak");
        beanDefinitionBuilder.addPropertyValue("idCard","522425199812290045");
        AbstractBeanDefinition userBeanDefinition = beanDefinitionBuilder.getBeanDefinition();
        System.out.println(userBeanDefinition);

        //注册Bean到Spring
        DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
        beanFactory.registerBeanDefinition("user",userBeanDefinition);

        //获取Bean
        User user = beanFactory.getBean("user", User.class);
        System.out.println(user);
    }
}

为Bean设置别名,因为BeanDefinitionRegistry继承了AliasRegistry,AliasRegistry提供了一些操作别名的方法,下面演示一些方法。

设置别名,获取别名
代码语言:javascript
复制
beanFactory.registerBeanDefinition("user",userBeanDefinition);
beanFactory.registerAlias("user","user-1");
beanFactory.registerAlias("user","user-2");
//获取Bean
User user = beanFactory.getBean("user", User.class);
for (String alias : beanFactory.getAliases("user")) {
    System.out.println(alias);
}

到这里Spring的Bean就注册完了,注册完Bean以后再继续做其他的操作。

4.Bean实例化

Bean实例化分为实例化前和实例化,实例化前会调用applyBeanPostProcessorsBeforeInitialization, 实例化会调用determineConstructorsFromBeanPostProcessors

applyBeanPostProcessorsBeforeInitialization实例化前操作

代码语言:javascript
复制
 @Override
 public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
   throws BeansException {
  Object result = existingBean;
  for (BeanPostProcessor processor : getBeanPostProcessors()) {
   Object current = processor.postProcessBeforeInitialization(result, beanName);
   if (current == null) {
    return result;
   }
   result = current;
  }
  return result;
 }

看出对getBeanPostProcessors()进行遍历操作,getBeanPostProcessors()是一个集合,泛型是BeanPostProcessor,BeanPostProcessor可以使我们 在对Bean进行实例化的时候做一些干扰,

代码语言:javascript
复制
private final List<BeanPostProcessor> beanPostProcessors = new BeanPostProcessorCacheAwareList();

对Bean实例化进行干扰

代码语言:javascript
复制
public class BeanInstanceBeforeTest{
    public static void main(String[] args) {
        DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
        beanFactory.addBeanPostProcessor(new BeanPostProcessor() {
            @Override
            public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
                if ("user".equals(beanName)){
                    return new User("liupai","123456");
                }
                return null;
            }
        });

        AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.rootBeanDefinition(User.class)
                .addPropertyValue("idCard", "111111")
                .addPropertyValue("username", "steak")
                .getBeanDefinition();
        beanFactory.registerBeanDefinition("user",beanDefinition);
        User user = beanFactory.getBean("user", User.class);
        System.out.println(user);
    }
}

在实例化前我们对Bean进行干扰,如果Bean为"user",那么对其重新赋值,我们从输出可以看出输出的并不是我们使用BeanDefinitionBuilder.addPropertyValue() 构造的值,而是在BeanPostProcessor构造的值,由此可以看出实例化过程已经被我们干扰,不过这样的操作一般不会用。

实例化

通过Bean的构造函数实例化Bean

代码语言:javascript
复制
 @Nullable
 protected Constructor<?>[] determineConstructorsFromBeanPostProcessors(@Nullable Class<?> beanClass, String beanName)
   throws BeansException {

  if (beanClass != null && hasInstantiationAwareBeanPostProcessors()) {
   for (SmartInstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().smartInstantiationAware) {
    Constructor<?>[] ctors = bp.determineCandidateConstructors(beanClass, beanName);
    if (ctors != null) {
     return ctors;
    }
   }
  }
  return null;
 }

实例化后

Bean实例化完成后会调用applyBeanPostProcessorsAfterInitialization方法

代码语言:javascript
复制
    @Override
 public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
   throws BeansException {

  Object result = existingBean;
  for (BeanPostProcessor processor : getBeanPostProcessors()) {
   Object current = processor.postProcessAfterInitialization(result, beanName);
   if (current == null) {
    return result;
   }
   result = current;
  }
  return result;
 }

我们也可以对实例化后的Bean进行干扰,下面我们将实例化后的Bean设置为空

代码语言:javascript
复制
public class BeanInstanceAfterTest{
    public static void main(String[] args) {
        DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
        beanFactory.addBeanPostProcessor(new BeanPostProcessor() {
            @Override
            public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
               if (beanName.equals("user")){
                   return new User(null,null);
               }
                return null;
            }
        });

        AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.rootBeanDefinition(User.class)
                .addPropertyValue("idCard", "111111")
                .addPropertyValue("username", "steak")
                .getBeanDefinition();
        beanFactory.registerBeanDefinition("user",beanDefinition);
        User user = beanFactory.getBean("user", User.class);
        System.out.println(user);
    }
}

从输出结果可以看出我们在实例化Bean以后可以对其进行干扰,只不过这样的操作很少会去用。

5.属性赋值

对Bean进行实例化后就到了属性赋值阶段,属性赋值阶段会调用InstantiationAwareBeanPostProcessorpostProcessProperties,下面我们手动进行属性赋值, 我们在构建 BeanDefinition时并没有设置属性,而是在进行实例化的时候再进行属性赋值,

代码语言:javascript
复制
public class BeanPropertiesTest {
    public static void main(String[] args) {
        DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
        beanFactory.addBeanPostProcessor(new InstantiationAwareBeanPostProcessor() {
            @Override
            public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {
               if (beanName.equals("user")){
                   MutablePropertyValues propertyValues = (MutablePropertyValues) pvs;
                   propertyValues.add("username","steak");
                   propertyValues.add("idCard","111111");
               }
               return null;
            }
        });

        AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.rootBeanDefinition(User.class)
                .getBeanDefinition();
        beanFactory.registerBeanDefinition("user",beanDefinition);
        User user = beanFactory.getBean("user", User.class);
        System.out.println(user);
    }
}

从输出可以看出属性设置成功。

如果在构建BeanDefinition的时候已经有属性值了,那么PropertyValues就会有相应的属性值(这些属性值是我们在XML或者注解中设置的值)

代码语言:javascript
复制
public class BeanPropertiesTest {
    public static void main(String[] args) {
        DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
        beanFactory.addBeanPostProcessor(new InstantiationAwareBeanPostProcessor() {
            @Override
            public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {
               return null;
            }
        });

        AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.rootBeanDefinition(User.class)
                .addPropertyValue("idCard", "222222")
                .addPropertyValue("username", "steak")
                .getBeanDefinition();
        beanFactory.registerBeanDefinition("user",beanDefinition);
        User user = beanFactory.getBean("user", User.class);
        System.out.println(user);
    }
}

6.Bean初始化

Bean Aware接口回调

Bean属性赋值成功以后会回调invokeAwareMethods,实现BeanNameAware , BeanClassLoaderAware , BeanFactoryAware接口的Bean,在Bean 初始化的时候会依次执行,如下。

实现BeanNameAware , BeanClassLoaderAware , BeanFactoryAware的Bean

代码语言:javascript
复制
public class UserAware implements BeanNameAware , BeanClassLoaderAware , BeanFactoryAware  {
    @Override
    public void setBeanClassLoader(ClassLoader classLoader) {
        System.out.println("classLoader  "+classLoader);
    }

    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        System.out.println("beanFactory   "+beanFactory);
    }

    @Override
    public void setBeanName(String name) {
        System.out.println("name  "+name);
    }
}

测试Bean

代码语言:javascript
复制
public class UserAwareTest {
    public static void main(String[] args) {
        BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.rootBeanDefinition(UserAware.class.getName());
        AbstractBeanDefinition userBeanDefinition = beanDefinitionBuilder.getBeanDefinition();

        //注册Bean
        DefaultListableBeanFactory defaultListableBeanFactory = new DefaultListableBeanFactory();
        defaultListableBeanFactory.registerBeanDefinition("userAware",userBeanDefinition);

        //获取Bean
        UserAware userAware = defaultListableBeanFactory.getBean("userAware", UserAware.class);
        System.out.println(userAware);
    }
}

由此看出,执行顺序是按照回调函数invokeAwareMethods的Bean判断顺序来执行的,顺序为BeanNameAware->BeanClassLoaderAware->BeanFactoryAware

Bean初始化前

Bean初始化前会调用BeanPostProcessor接口的postProcessBeforeInitialization作初始化操作,BeanPostProcessor, 看下BeanPostProcessor的两个实现类 CommonAnnotationBeanPostProcessorApplicationContextAwareProcessor

ApplicationContextAwareProcessorinvokeAwareInterfaces中有7个判断,如果我们的Bean实现了这7个Aware接口,那么将会依次执行这 7个接口的方法,CommonAnnotationBeanPostProcessor是处理@PostConstruct的处理器

ApplicationContextAwareProcessor

代码语言:javascript
复制
    private void invokeAwareInterfaces(Object bean) {
  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 ApplicationStartupAware) {
   ((ApplicationStartupAware) bean).setApplicationStartup(this.applicationContext.getApplicationStartup());
  }
  if (bean instanceof ApplicationContextAware) {
   ((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
  }
 }

CommonAnnotationBeanPostProcessor

代码语言:javascript
复制
public CommonAnnotationBeanPostProcessor(){
        setOrder(Ordered.LOWEST_PRECEDENCE-3);
        setInitAnnotationType(PostConstruct.class);
        setDestroyAnnotationType(PreDestroy.class);
        ignoreResourceType("javax.xml.ws.WebServiceContext");

        // java.naming module present on JDK 9+?
        if(jndiPresent){
        this.jndiFactory=new SimpleJndiBeanFactory();
        }
}

实现7个Aware接口和编写一个@PostConstruct注解的方法

代码语言:javascript
复制
public class UserApplicationContextAware implements EnvironmentAware , EmbeddedValueResolverAware , ResourceLoaderAware,
        ApplicationEventPublisherAware, MessageSourceAware,ApplicationStartupAware,ApplicationContextAware {
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        System.out.println("applicationContext  "+applicationContext);
    }
    @Override
    public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
        System.out.println("applicationEventPublisher  "+applicationEventPublisher);
    }
    @Override
    public void setApplicationStartup(ApplicationStartup applicationStartup) {
        System.out.println("applicationStartup  "+applicationStartup);
    }
    @Override
    public void setEmbeddedValueResolver(StringValueResolver resolver) {
        System.out.println("resolver  "+resolver);
    }
    @Override
    public void setEnvironment(Environment environment) {
        System.out.println("environment  "+environment);
    }
    @Override
    public void setMessageSource(MessageSource messageSource) {
        System.out.println("messageSource  "+messageSource);
    }
    @Override
    public void setResourceLoader(ResourceLoader resourceLoader) {
        System.out.println("resourceLoader  "+resourceLoader);
    }
    @PostConstruct
    public void PostConstructTest(){
        System.out.println("PostConstruct SimpleTest");
    }
}

测试

代码语言:javascript
复制
public class UserApplicationContextAwareTest {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
        context.register(UserApplicationContextAware.class);
        context.refresh();
    }
}

可以看出实现了EnvironmentAware , EmbeddedValueResolverAware , ResourceLoaderAware, ApplicationEventPublisherAware, MessageSourceAware,ApplicationStartupAware,ApplicationContextAware这七个接口,将会按照ApplicationContextAwareProcessorinvokeAwareInterfaces顺序执行

Bean初始化

Bean在初始化的时候会调用InitializingBean接口的afterPropertiesSet()方法。

代码语言:javascript
复制
public interface InitializingBean {
 void afterPropertiesSet() throws Exception;
}

如果我们指定了Bean的初始化方法,那么在调用完afterPropertiesSet()方法后会调用我们自定义的初始化方法

定义一个Bean并实现InitializingBean

代码语言:javascript
复制
public class BusinessService implements InitializingBean {
    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("after ");
    }
    /**
     * 初始化方法
     */
    public void init(){
        System.out.println("init");
    }
}

配置Bean并设置初始化方法

可以通过@Bean(initMethod = "init")这种方式来设置Bean的初始化方法,这个方法就是BusinessServiceBean中的 init()方法,

代码语言:javascript
复制
@Configuration
public class BeanConfig{

    @Bean(initMethod = "init")
    public BusinessService businessService(){
        return new BusinessService();
    }
}

测试

代码语言:javascript
复制
public class ConfigBeanTest {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(BeanConfig.class);
    }
}

从输出看出先执行afterPropertiesSet()在执行我们自定义的初始化方法。

Bean初始化后

Bean初始化完成后会调用BeanPostProcessor接口的postProcessAfterInitialization()方法。

7.Bean初始化完成后阶段

所有单例Bean初始化完成之后会调用SmartInitializingSingleton接口的afterSingletonsInstantiated()方法,逻辑如下

代码语言:javascript
复制
    for (String beanName : beanNames) {
   Object singletonInstance = getSingleton(beanName);
   if (singletonInstance instanceof SmartInitializingSingleton) {
    StartupStep smartInitialize = this.getApplicationStartup().start("spring.beans.smart-initialize")
      .tag("beanName", beanName);
    SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
    if (System.getSecurityManager() != null) {
     AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
      smartSingleton.afterSingletonsInstantiated();
      return null;
     }, getAccessControlContext());
    }
    else {
     smartSingleton.afterSingletonsInstantiated();
    }
    smartInitialize.end();
   }
  }

Bean1

代码语言:javascript
复制
public class Bean1 {
    public Bean1(){
        System.out.println("bean1  ");
    }
}

Bean2

代码语言:javascript
复制
public class Bean2 {
    public Bean2(){
        System.out.println("bean2");
    }
}

BeanInitOverConfig实现SmartInitializingSingleton

代码语言:javascript
复制
@Configuration
public class BeanInitOverConfig implements SmartInitializingSingleton {
    @Override
    public void afterSingletonsInstantiated() {
        System.out.println("所有单例bean初始化完成之后调用");
    }
    @Bean
    public Bean1 bean1(){
        return new Bean1();
    }
    @Bean
    public Bean2 bean2(){
        return new Bean2();
    }
}

测试

代码语言:javascript
复制
public class BeanInitOverTest {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(BeanInitOverConfig.class);
    }
}

从输出可以看出Bean1和Bean2输出后afterSingletonsInstantiated()再输出,由此证明所有单例Bean初始化完成后会调用SmartInitializingSingletonafterSingletonsInstantiated()方法。

8.使用Bean

初始化完成Bean后就可以使用Bean,使用Bean使用getBean方法便可,

代码语言:javascript
复制
public class BeanInitOverTest {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(BeanInitOverConfig.class);
        Bean1 bean1 = context.getBean("bean1", Bean1.class);
    }
}

9.销毁Bean

Bean的销毁可以使用@PreDestroy注解,自定义销毁方法,实现DisposableBean接口。

定义一个Bean,并使用三种销毁bean的方式

代码语言:javascript
复制
public class Bean1 implements DisposableBean {
    public Bean1(){
        System.out.println("bean1  ");
    }
    /**
     * 自定义销毁方法
     */
    public void bean1Destroy(){
        System.out.println("销毁bean1");
    }
    /**
     * 实现DisposableBean
     * @throws Exception
     */
    @Override
    public void destroy() throws Exception {
        System.out.println("继承DisposableBean销毁bean");
    }
    /**
     * 使用@PreDestroy
     */
    @PreDestroy
    public void preDestroy(){
        System.out.println("@PreDestroy销毁bean");
    }
}

Bean配置类,指定自定义销毁方法

代码语言:javascript
复制
@Configuration
public class BeanDestroyConfig{

    @Bean(destroyMethod = "bean1Destroy")
    public Bean1 bean1(){
        return new Bean1();
    }
}

测试,使用AnnotationConfigApplicationContextclose触发销毁bean

代码语言:javascript
复制
public class BeanDestroyTest {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(BeanDestroyConfig.class);
        context.close();
    }
}

可以看出使用销毁顺序优先级为@PreDestroy > 实现DisposableBean > 自定义方法

使用@PreDestroy销毁Bean,它会调用DestructionAwareBeanPostProcessorpostProcessBeforeDestruction,postProcessBeforeDestruction在它的实现类InitDestroyAnnotationBeanPostProcessor中进行销毁

代码语言:javascript
复制
@Override
 public void postProcessBeforeDestruction(Object bean, String beanName) throws BeansException {
  LifecycleMetadata metadata = findLifecycleMetadata(bean.getClass());
  try {
   metadata.invokeDestroyMethods(bean, beanName);
  }
  catch (InvocationTargetException ex) {
   String msg = "Destroy method on bean with name '" + beanName + "' threw an exception";
   if (logger.isDebugEnabled()) {
    logger.warn(msg, ex.getTargetException());
   }
   else {
    logger.warn(msg + ": " + ex.getTargetException());
   }
  }
  catch (Throwable ex) {
   logger.warn("Failed to invoke destroy method on bean with name '" + beanName + "'", ex);
  }
 }

CommonAnnotationBeanPostProcessor@PreDestroy进行管理,它继承了InitDestroyAnnotationBeanPostProcessor

到这里,Bean的生命周期就说完了。

今天的分享就到这里,感谢你的观看,我们下期见

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2022-06-26,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 刘牌 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 码农在囧途
  • 前言
  • Spring Bean的生命周期图
  • 1.Bean元信息配置
    • XML方式
      • 构造注入
      • set注入
    • 注解方式
      • 使用@Configuration和@Bean
        • 使用@Component,@Service,@Controller等注解申明一个Bean
          • 使用BeanDefinition直接配置一个Bean
          • 2.Bean元信息解析阶段
            • 解析XML
              • 解析注解
              • 3.将Bean注册到Spring容器中
                • BeanDefinitionRegistry
                  • AliasRegistry
                    • 注册Bean
                      • 为Bean设置别名,因为BeanDefinitionRegistry继承了AliasRegistry,AliasRegistry提供了一些操作别名的方法,下面演示一些方法。
                      • 4.Bean实例化
                        • applyBeanPostProcessorsBeforeInitialization实例化前操作
                          • 对Bean实例化进行干扰
                            • 实例化
                              • 实例化后
                              • 5.属性赋值
                              • 6.Bean初始化
                                • Bean Aware接口回调
                                  • 实现BeanNameAware , BeanClassLoaderAware , BeanFactoryAware的Bean
                                    • 测试Bean
                                      • Bean初始化前
                                        • ApplicationContextAwareProcessor
                                          • CommonAnnotationBeanPostProcessor
                                            • 实现7个Aware接口和编写一个@PostConstruct注解的方法
                                              • 测试
                                                • Bean初始化
                                                  • 定义一个Bean并实现InitializingBean
                                                    • 配置Bean并设置初始化方法
                                                      • 测试
                                                        • Bean初始化后
                                                        • 7.Bean初始化完成后阶段
                                                          • Bean1
                                                            • Bean2
                                                              • BeanInitOverConfig实现SmartInitializingSingleton
                                                                • 测试
                                                                • 8.使用Bean
                                                                • 9.销毁Bean
                                                                  • 定义一个Bean,并使用三种销毁bean的方式
                                                                    • Bean配置类,指定自定义销毁方法
                                                                      • 测试,使用AnnotationConfigApplicationContext的close触发销毁bean
                                                                      相关产品与服务
                                                                      容器服务
                                                                      腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
                                                                      领券
                                                                      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档