利用springboot2.x怎么解决Bean对象注入顺序的问题

发布时间:2021-01-06 15:11:10 作者:Leah
来源:亿速云 阅读:276

今天就跟大家聊聊有关利用springboot2.x怎么解决Bean对象注入顺序的问题,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。

1 前言

通过指定接口,重写指定方法,可以在Bean对应的生命周期方法中执行相应的程序

2 测试

<?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 实验结果

利用springboot2.x怎么解决Bean对象注入顺序的问题 

销毁的顺序

利用springboot2.x怎么解决Bean对象注入顺序的问题 

3 @Dependon 和 @Order

4 利用BeanFactoryPostProcessor 初始化

4.1 一般初始化

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 按序初始化

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 实现冯诺依曼结构

package com.wu.smartport.test;

import com.wu.smartport.SmartportApplication;
import javafx.stage.Stage;
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
 */
public class Manager implements BeanFactoryPostProcessor {
 @Override
 public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
  // 执行方法告诉javaFx
  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 javafx.application.Application;
import javafx.stage.Stage;
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();
  }
 }
}

看完上述内容,你们对利用springboot2.x怎么解决Bean对象注入顺序的问题有进一步的了解吗?如果还想了解更多知识或者相关内容,请关注亿速云行业资讯频道,感谢大家的支持。

推荐阅读:
  1. spring注入对象的方法和创建bean的步骤
  2. vue 解决遍历对象显示的顺序不对问题

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

springboot bea bean

上一篇:method在golang中的作用是什么

下一篇:interface在Golang语言中有什么用

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》