springboot2.x 的骚操作——解决运行顺序以及Bean对象注入顺序的问题

1 前言

  • 通过指定接口,重写指定方法,可以在Bean对应的生命周期方法中执行相应的程序
  • 在项目当中最让人头疼的就是bean对象不被注入的问题,通过本文,你可以很好的解决这个问题。

2 测试

  • 本文将分析几个Bean对象,为它们设置优先级(通过@Order),然后再打断点调试,测试各种生命周期方法的运行的顺序
  • 本文中将测试以下几个spring提供的接口(对Bean对象使用,下面几个接口提供的方法是有先后运行顺序的,对于单个Bean而言。运行的顺序和我这里给出的接口的顺序一致。)
    • BeanNameAware
    • BeanFactoryAware
    • ApplicationContextAware
    • InitializingBean
    • BeanDefinitionRegistryPostProcessor,BeanFactoryPostProcessor,前者实现了后者。
      • 使用这两个接口时要注意,经测试,只要bean对象继承这两个其中的任意一个接口,都会导致Bean对象内部的@Autowired等注入方法失效。即便使用@Order设置优先级和使用@Dependon设置依赖,也不能让bean对象注入到成员变量中
      • 但是这两个接口提供了两个形参含有BeanFactory的方法,并且这两个方法是在所有bean对象被注入spring后(正常方式,不包括随后手动注入的)才会调用的,所以你可以在这两个方法内部手动提取Bean对象。
      • 也就是说,只要你的Bean对象实现了该接口,spring就会认为你是要自己去提取bean对象,于是就不帮你自动注入了。
      • 被@Autowired 注释的Bean对象实现这个接口后,依然能被自动注入。例如MainController 中需要注入MainService,在MainService上标记@Autowied。而MainService实现了BeanDefinitionRegistryPostProcessor接口,但MainService依然能被合理地注入到MainController的成员变量里。
    • BeanPostProcessor(该接口下文没使用,大家可以自己试试)
    • DisposableBean
      • 在bean对象被销毁的时候,spring会调用该接口提供的方法。
      • 注意,如果程序中还有其他线程在持续运行,则Springboot不会主动关闭,也不会调用destroy()方法。即便你在启动类中使用ConfigurableApplicationContext 对象的stop方法也无效。spring必须等待其他线程释放资源以后才能退出程序。
  • 先看看本程序使用的依赖
<?xml version="1.0" encoding="UTF-8"?>
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.0.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.wu</groupId>
    <artifactId>smartport</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>smartport</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

2.1 Order = 1

package com.wu.smartport.controller;

import com.wu.smartport.test.User;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

@Component
@Order(1)
public class TestController implements BeanNameAware, BeanFactoryAware, ApplicationContextAware, BeanDefinitionRegistryPostProcessor, InitializingBean, DisposableBean {
    @Autowired
    private User user;

    /**
     * 最先执行,需要接口BeanNameAware
     *
     * @param name
     */
    @Override
    public void setBeanName(String name) {
        // 获取到的是testController,即注入进Spring中的名称
        System.out.println("setBeanName:" + name);
    }

    /**
     * 第2个执行,需要接口BeanFactoryAware
     * beanFactory可以获取其他已注入的Bean对象,但无法注入其他对象
     *
     * @param beanFactory
     * @throws BeansException
     */
    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {

    }

    /**
     * 第3个执行,需要ApplicationContextAware接口
     * 可以获取到上下文对象applicationContext,允许容器通过应用程序上下文环境创建、获取、管理bean
     *
     * @param applicationContext
     * @throws BeansException
     */
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        // 可以通过上下文对象获取工厂并注入对象
        AutowireCapableBeanFactory beanFactory = applicationContext.getAutowireCapableBeanFactory();

    }

    /**
     * 第4个执行,依赖于InitializingBean接口
     *
     * @throws Exception
     */
    @Override
    public void afterPropertiesSet() throws Exception {

    }

    /**
     * 第5个执行,依赖于BeanDefinitionRegistryPostProcessor接口
     * 当完成本方法后,对象就会完成注入
     * @param registry
     * @throws BeansException
     */
    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {

    }

    /**
     * 第6个执行,来源于BeanFactoryPostProcessor接口,该接口被BeanDefinitionRegistryPostProcessor接口实现了。
     * 一般的Bean对象在此方法前都被注入到了容器中,如果本对象没有获取到,则可以在这里获取。
     * @param beanFactory
     * @throws BeansException
     */
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        Object user = beanFactory.getBean("user");
    }

    /**
     * 第7个执行,本方法将被多次执行,依赖于BeanPostProcessor接口
     * 每注入一个对象的时候,都会调用该方法
     * @param bean
     * @param beanName
     * @return
     * @throws BeansException
     */

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

    /**
     * 第8个执行,本方法将被多次执行,依赖于BeanPostProcessor接口
     * 每注入一个对象之后,都会调用该方法
     * @param bean
     * @param beanName
     * @return
     * @throws BeansException
     */

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

    /**
     * 在本对象被销毁后执行,依赖于DisposableBean接口
     * @throws Exception
     */
    @Override
    public void destroy() throws Exception {

    }
}

2.2 Order = 15

package com.wu.smartport.test;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.*;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Service;

/**
 * @Author :吴用
 * @Date :2021-01-05 8:40
 * @Version :1.0
 */
@Service
@Order(15)
public class User implements BeanNameAware, BeanFactoryAware, ApplicationContextAware, BeanDefinitionRegistryPostProcessor, InitializingBean, DisposableBean {
    @Value("张三")
    private String name;
    @Value("12")
    private int age;

    public User() {
    }



    public User(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    /**
     * 最先执行,需要接口BeanNameAware
     *
     * @param name
     */
    @Override
    public void setBeanName(String name) {
        System.out.println("setBeanName:" + name);
    }

    /**
     * 第2个执行,需要接口BeanFactoryAware
     * beanFactory可以获取其他已注入的Bean对象,但无法注入其他对象
     *
     * @param beanFactory
     * @throws BeansException
     */
    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {

    }

    /**
     * 第3个执行,需要ApplicationContextAware接口
     * 可以获取到上下文对象applicationContext,允许容器通过应用程序上下文环境创建、获取、管理bean
     *
     * @param applicationContext
     * @throws BeansException
     */
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {

    }

    /**
     * 第4个执行,依赖于InitializingBean接口
     *
     * @throws Exception
     */
    @Override
    public void afterPropertiesSet() throws Exception {

    }

    /**
     * 第5个执行,依赖于BeanDefinitionRegistryPostProcessor接口
     * 当完成本方法后,对象就会完成注入
     * @param registry
     * @throws BeansException
     */
    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {

    }

    /**
     * 第6个执行,来源于BeanFactoryPostProcessor接口,该接口被BeanDefinitionRegistryPostProcessor接口实现了。
     * 一般的Bean对象在此方法前都被注入到了容器中,如果本对象没有获取到,则可以在这里获取。
     * @param beanFactory
     * @throws BeansException
     */
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        Object user = beanFactory.getBean("user");
    }

    /**
     * 第7个执行,本方法将被多次执行,依赖于BeanPostProcessor接口
     * 每注入一个对象的时候,都会调用该方法
     * @param bean
     * @param beanName
     * @return
     * @throws BeansException
     */

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

    /**
     * 第8个执行,本方法将被多次执行,依赖于BeanPostProcessor接口
     * 每注入一个对象之后,都会调用该方法
     * @param bean
     * @param beanName
     * @return
     * @throws BeansException
     */

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

    /**
     * 在本对象被销毁后执行,依赖于DisposableBean接口
     * @throws Exception
     */
    @Override
    public void destroy() throws Exception {

    }
}

2.3 Order = 30

package com.wu.smartport.test;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.*;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

/**
 * @Author :吴用
 * @Date :2021-01-05 9:48
 * @Version :1.0
 */
@Order(30)
@Component
public class User2 implements BeanNameAware, BeanFactoryAware, ApplicationContextAware, BeanDefinitionRegistryPostProcessor, InitializingBean, DisposableBean {
    @Value("张三")
    private String name;
    @Value("12")
    private int age;

    public User2() {
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }



    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }


    /**
     * 最先执行,需要接口BeanNameAware
     *
     * @param name
     */
    @Override
    public void setBeanName(String name) {
        System.out.println("setBeanName:" + name);
    }

    /**
     * 第2个执行,需要接口BeanFactoryAware
     * beanFactory可以获取其他已注入的Bean对象,但无法注入其他对象
     *
     * @param beanFactory
     * @throws BeansException
     */
    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {

    }

    /**
     * 第3个执行,需要ApplicationContextAware接口
     * 可以获取到上下文对象applicationContext,允许容器通过应用程序上下文环境创建、获取、管理bean
     *
     * @param applicationContext
     * @throws BeansException
     */
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {

    }

    /**
     * 第4个执行,依赖于InitializingBean接口
     *
     * @throws Exception
     */
    @Override
    public void afterPropertiesSet() throws Exception {

    }

    /**
     * 第5个执行,依赖于BeanDefinitionRegistryPostProcessor接口
     * 当完成本方法后,对象就会完成注入
     * @param registry
     * @throws BeansException
     */
    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {

    }

    /**
     * 第6个执行,来源于BeanFactoryPostProcessor接口,该接口被BeanDefinitionRegistryPostProcessor接口实现了。
     * 一般的Bean对象在此方法前都被注入到了容器中,如果本对象没有获取到,则可以在这里获取。
     * @param beanFactory
     * @throws BeansException
     */
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        Object user = beanFactory.getBean("user");
    }

    /**
     * 第7个执行,本方法将被多次执行,依赖于BeanPostProcessor接口
     * 每注入一个对象的时候,都会调用该方法
     * @param bean
     * @param beanName
     * @return
     * @throws BeansException
     */

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

    /**
     * 第8个执行,本方法将被多次执行,依赖于BeanPostProcessor接口
     * 每注入一个对象之后,都会调用该方法
     * @param bean
     * @param beanName
     * @return
     * @throws BeansException
     */

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

    /**
     * 在本对象被销毁后执行,依赖于DisposableBean接口
     * @throws Exception
     */
    @Override
    public void destroy() throws Exception {

    }
}

2.4 实验结果

  • 如下图所示
  • TestController 的Order=1,最高优先级
  • User 的 Order = 15,中等优先级
  • User2 的 Order = 30,低优先级
  • 前四个方法会按照优先级的顺序先后执行,然后按优先级顺序执行postProcessBeanDefinitionRegistry方法,然后再按优先级顺序执行postProcessBeanFactory方法
    • postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) 方法很不错,给了beanFactory。不仅如此,在此方法以前,所有的Bean对象已经被注入完毕了,所以如果之前你的对象没有注入进去,你就可以在这里通过beanFactroy获取对象,然后把对象重新注入进去。
    • 但是还是得重申一遍,实现了BeanDefinitionRegistryPostProcessor或者BeanFactoryPostProcessor接口后,会导致@Autowired,@Resource等注入方法无效,这点要切记!
      在这里插入图片描述
  • 销毁的顺序
    在这里插入图片描述

3 @Dependon 和 @Order

  • @Dependon 和@Order 共同决定Bean对象的注入顺序,
  • 如果A对象 @Dependon B对象,则无论A对象和B对象的@Order的值是什么,都以@Dependon标签为主
    • 例如A对象@Dependon(“b”),@Order(1) ,B对象@Order(15),则B对象将先于A对象注入spring容器中

4 利用BeanFactoryPostProcessor 初始化

4.1 一般初始化

  • 根据上面的实验我们知道实现BeanFactoryPostProcessor接口后,重写void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)
    • 在该方法运行时,所有的bean对象都已经被注入到了spring容器中,此时可以利用观察者模式将你需要初始化的对象进行初始化。
  • 首先,需要写一个ObserverForInit接口
package com.wu.smartport.controller;

/**
 * 观察者,用于初始化
 * @Author :吴用
 * @Date :2021-01-05 11:02
 * @Version :1.0
 */
public interface ObserverForInit {
    /**
     * 观察者初始化
     */
    void observerInit();
}
  • 再让需要初始化操作的bean对象实现该接口
package com.wu.smartport.test;

import com.wu.smartport.controller.ObserverForInit;
import org.springframework.stereotype.Component;

/**
 * @Author :吴用
 * @Date :2021-01-05 11:11
 * @Version :1.0
 */
@Component
public class User implements ObserverForInit {
    @Override
    public void observerInit() {
        System.out.println("我要进行初始化了!");
    }
}
  • 然后再写一个管理bean初始化的类
    • 通过遍历所有的Bean对象,然后查询指定的接口或者自定义注解,执行相应的操作(比如初始化操作。)
package com.wu.smartport.manager;

import com.wu.smartport.controller.ObserverForInit;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanCreationException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.stereotype.Component;

import java.util.Iterator;

/**
 * @Author :吴用
 * @Date :2021-01-05 11:06
 * @Version :1.0
 */
@Component
public class ControllerInitManager implements BeanFactoryPostProcessor {
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        Iterator<String> its = beanFactory.getBeanNamesIterator();
        while (its.hasNext()) {
            String beanName = its.next();
            try {
                Object bean = beanFactory.getBean(beanName);
                analysisObject(bean);
            } catch (BeanCreationException e) {
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 分析bean对象
     *
     * @param bean
     */
    private void analysisObject(Object bean) {
        analysisInterface(bean);
        analysisAnnotation(bean);
    }


    /**
     * 分析接口
     *
     * @param bean
     */
    private void analysisInterface(Object bean) {
        Class<?> beanClass = bean.getClass();
        // 分析Interface 和 Annotation
        Class<?>[] interfaces = beanClass.getInterfaces();
        // 分析Class
        for (Class infs : interfaces) {
            if (infs.equals(ObserverForInit.class)) {
                ((ObserverForInit) bean).observerInit();
            }
        }
    }

    /**
     * 分析注解
     *
     * @param bean
     */
    private void analysisAnnotation(Object bean) {

    }
}

4.2 按序初始化

  • 如果对初始化的顺序有自己要求,可以采取如下的方法。至于4.1中的遍历顺序,读者可以自行研究,但建议自己写顺序,否则一旦springboot框架内部有变,咱们程序内部的初始顺序可能会出问题。
  • 设置一个TreeSet 并给定排序策略,遍历接口的时候,先将找到的对象放入TreeSet中排序,再遍历完成之后再执行相应的操作
  • 修改后的接口
package com.wu.smartport.controller;

/**
 * 观察者,用于初始化
 * @Author :吴用
 * @Date :2021-01-05 11:02
 * @Version :1.0
 */
public interface ObserverForInit {
    /**
     * 观察者初始化
     */
    void observerInit();

    /**
     * 初始化的顺序,数越小,优先级越高
     * @return
     */
    int getInitOrder();
}
  • bean对象
/**
 * @Author :吴用
 * @Date :2021-01-04 22:51
 * @Version :1.0
 */
@Component
public class PageManager implements ObserverForInit {
    @Override
    public void observerInit() {
        System.out.println("PageManager初始化");
    }

    @Override
    public int getInitOrder() {
        return 1000;
    }
}
  • 管理初始化的类
package com.wu.smartport.manager;

import com.wu.smartport.controller.ObserverForInit;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanCreationException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.stereotype.Component;
import java.util.Comparator;
import java.util.Iterator;
import java.util.TreeSet;

/**
 * @Author :吴用
 * @Date :2021-01-05 11:06
 * @Version :1.0
 */
@Component
public class ControllerInitManager implements BeanFactoryPostProcessor {
    private TreeSet<ObserverForInit> inits = new TreeSet<>(Comparator.comparingInt(ObserverForInit::getInitOrder));

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        Iterator<String> its = beanFactory.getBeanNamesIterator();
        while (its.hasNext()) {
            String beanName = its.next();
            try {
                Object bean = beanFactory.getBean(beanName);
                analysisObject(bean);
            } catch (BeanCreationException e) {
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        // 遍历完成后的操作
        analysisByAfterIterator();
    }


    /**
     * 分析bean对象
     *
     * @param bean
     */
    private void analysisObject(Object bean) {
        analysisInterface(bean);
        analysisAnnotation(bean);
    }

    /**
     * 遍历之后的操作
     */
    private void analysisByAfterIterator() {
        // 按照指定的顺序遍历
        // 升序遍历,order小的先执行初始化方法
        for (ObserverForInit o : inits) {
            o.observerInit();
        }
    }

    /**
     * 分析接口
     *
     * @param bean
     */
    private void analysisInterface(Object bean) {
        Class<?> beanClass = bean.getClass();
        // 分析Interface 和 Annotation
        Class<?>[] interfaces = beanClass.getInterfaces();
        // 分析Class
        for (Class infs : interfaces) {
            if (infs.equals(ObserverForInit.class)) {
                inits.add((ObserverForInit) bean);
            }
        }
    }

    /**
     * 分析注解
     *
     * @param bean
     */
    private void analysisAnnotation(Object bean) {

    }
}

5 基于 Springboot 实现冯诺依曼结构

  • 下面讲解一个骚操作
  • 冯诺依曼结构:将程序和数据分别存储在内存当中
  • 基于这种思想,我们不光可以把数据存储在容器当中,我们还可以把代码也存储在springboot容器当中。
  • 创建一个Bean对象,实现BeanFactoryPostProcessor接口,在运行到该方法的时候,大部分的对象已经被装入了spring容器中。你可以在之后必要的地方从spring容器中提取该代码执行。
package com.wu.smartport.test;

import com.wu.smartport.SmartportApplication;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;

import java.io.IOException;
import java.util.ArrayList;
import java.util.function.Function;

import static com.wu.smartport.config.BeanInitOrder.INIT_METHODS;
import static com.wu.smartport.config.BeanInitOrder.STAGE_BEAN;

/**
 * @Author :吴用
 * @Date :2021-01-05 19:27
 * @Version :1.0
 */
@Component
public class Manager implements BeanFactoryPostProcessor {
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        ArrayList<Function> arr;
        try{
            // 尝试从容器中获取代码块
            Object bean = beanFactory.getBean("function");
            arr = (ArrayList<Function>)bean;
        }catch (Exception e2){
            // 如果不存在则创建代码块
            arr = new ArrayList<>();
        }
        // 书写一段代码
        Function<Void,Void> f = aVoid -> {
            // 相关的业务
            return null;
        };
        arr.add(f);
        // 将代码块注入到spring容器中
        DefaultListableBeanFactory factory = (DefaultListableBeanFactory)beanFactory;
        factory.registerSingleton(INIT_METHODS,arr);
    }
}
  • 在之后一定会运行到的代码,比如启动类之后,可以执行指定的代码段。
package com.wu.smartport;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import java.util.ArrayList;
import java.util.function.Function;
import static com.wu.smartport.config.BeanInitOrder.INIT_METHODS;
import static com.wu.smartport.config.BeanInitOrder.STAGE_BEAN;

/**
 * 主启动类
 * @author Wu_Sir
 */
@SpringBootApplication
public class SmartportApplication{
    private static volatile ConfigurableApplicationContext run;

    /**
     * 主程序入口
     *
     * @param args
     */
    public static void main(String[] args) {
        run = SpringApplication.run(SmartportApplication.class, args);
        // 查看是否有要处理的方法
        try{
            Object bean = beanFactory.getBean("function");
            ArrayList<Function> arr = (ArrayList<Function>) bean;
            for (int i = 0; i < arr.size(); i++) {
            	//如果有,则执行该方法。
                Function f = arr.get(i);
                f.apply(null);
            }
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值