热门标签 | HotTags
当前位置:  开发笔记 > 运维 > 正文

springboot2.x解决运行顺序及Bean对象注入顺序的问题

这篇文章主要介绍了springboot2.x解决运行顺序及Bean对象注入顺序的问题,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

1 前言

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

2 测试

  • 本文将分析几个Bean对象,为它们设置优先级(通过@Order),然后再打断点调试,测试各种生命周期方法的运行的顺序
  • 在项目当中最让人头疼的就是bean对象不被注入的问题,通过本文,你可以很好的解决这个问题。
  • 先看看本程序使用的依赖
<&#63;xml version="1.0" encoding="UTF-8"&#63;>

 4.0.0
 
  org.springframework.boot
  spring-boot-starter-parent
  2.3.0.RELEASE
   
 
 com.wu
 smartport
 0.0.1-SNAPSHOT
 smartport
 Demo project for Spring Boot

 
  1.8
 

 
  
   org.springframework.boot
   spring-boot-starter
  

  
   org.projectlombok
   lombok
   true
  
  
   org.springframework.boot
   spring-boot-starter-test
   test
  
 

 
  
   
    org.springframework.boot
    spring-boot-maven-plugin
    
     
      
       org.projectlombok
       lombok
      
     
    
   
  
 

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获取对象,然后把对象重新注入进去。

在这里插入图片描述 

销毁的顺序

在这里插入图片描述 

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 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<&#63;> beanClass = bean.getClass();
  // 分析Interface 和 Annotation
  Class<&#63;>[] 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 inits = new TreeSet<>(Comparator.comparingInt(ObserverForInit::getInitOrder));

 @Override
 public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
  Iterator 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<&#63;> beanClass = bean.getClass();
  // 分析Interface 和 Annotation
  Class<&#63;>[] 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 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 arr;
  try{
   // 尝试从容器中获取代码块
   Object bean = beanFactory.getBean("function");
   arr = (ArrayList)bean;
  }catch (Exception e2){
   // 如果不存在则创建代码块
   arr = new ArrayList<>();
  }
  // 书写一段代码
  Function 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 arr = (ArrayList) bean;
   for (int i = 0; i 

到此这篇关于springboot2.x解决运行顺序及Bean对象注入顺序的问题的文章就介绍到这了,更多相关springboot注入Bean顺序内容请搜索以前的文章或继续浏览下面的相关文章希望大家以后多多支持!


推荐阅读
  • 简化报表生成:EasyReport工具的全面解析
    本文详细介绍了EasyReport,一个易于使用的开源Web报表工具。该工具支持Hadoop、HBase及多种关系型数据库,能够将SQL查询结果转换为HTML表格,并提供Excel导出、图表显示和表头冻结等功能。 ... [详细]
  • 深入解析SpringMVC核心组件:DispatcherServlet的工作原理
    本文详细探讨了SpringMVC的核心组件——DispatcherServlet的运作机制,旨在帮助有一定Java和Spring基础的开发人员理解HTTP请求是如何被映射到Controller并执行的。文章将解答以下问题:1. HTTP请求如何映射到Controller;2. Controller是如何被执行的。 ... [详细]
  • docker镜像重启_docker怎么启动镜像dock ... [详细]
  • 近期我们开发了一款包含天气预报功能的万年历应用,为了满足这一需求,团队花费数日时间精心打造并测试了一个稳定可靠的天气API接口,现正式对外开放。 ... [详细]
  • 深入解析Hadoop的核心组件与工作原理
    本文详细介绍了Hadoop的三大核心组件:分布式文件系统HDFS、资源管理器YARN和分布式计算框架MapReduce。通过分析这些组件的工作机制,帮助读者更好地理解Hadoop的架构及其在大数据处理中的应用。 ... [详细]
  • 烤鸭|本文_Spring之Bean的生命周期详解
    烤鸭|本文_Spring之Bean的生命周期详解 ... [详细]
  • 本文详细介绍了如何正确安装Java EE SDK,并解决在安装过程中可能遇到的问题,特别是关于servlet代码在Apache Tomcat 10中无法运行的情况。 ... [详细]
  • 深入解析Serverless架构模式
    本文将详细介绍Serverless架构模式的核心概念、工作原理及其优势。通过对比传统架构,探讨Serverless如何简化应用开发与运维流程,并介绍当前主流的Serverless平台。 ... [详细]
  • Spring Boot 中静态资源映射详解
    本文深入探讨了 Spring Boot 如何简化 Web 应用中的静态资源管理,包括默认的静态资源映射规则、WebJars 的使用以及静态首页的处理方法。通过本文,您将了解如何高效地管理和引用静态资源。 ... [详细]
  • SpringMVC RestTemplate的几种请求调用(转)
    SpringMVCRestTemplate的几种请求调用(转),Go语言社区,Golang程序员人脉社 ... [详细]
  • ArcXML:互联网空间数据交换的专用语言
    ArcXML是一种专为ArcIMS平台设计的数据交换协议,基于XML标准,用于在不同组件之间传输和描述地理空间数据。本文将详细介绍ArcXML的背景、用途及其与XML的关系。 ... [详细]
  • 本文详细介绍如何使用 Python 集成微信支付的三种主要方式:Native 支付、APP 支付和 JSAPI 支付。每种方式适用于不同的应用场景,如 PC 网站、移动端应用和公众号内支付等。 ... [详细]
  • 搭建Jenkins、Ant与TestNG集成环境
    本文详细介绍了如何在Ubuntu 16.04系统上配置Jenkins、Ant和TestNG的集成开发环境,涵盖从安装到配置的具体步骤,并提供了创建Windows Slave节点及项目构建的指南。 ... [详细]
  • 优化Jenkins首次启动速度
    本文详细描述了在启动Jenkins后遇到的长时间加载问题,并提供了一种通过修改更新中心配置文件来显著提升启动速度的有效解决方案。 ... [详细]
  • Eclipse 中 JSP 开发环境配置指南
    本文详细介绍了如何在 Eclipse 集成开发环境中配置 JSP 运行环境,包括必要的软件下载、Tomcat 服务器的配置以及常见问题的解决方法。 ... [详细]
author-avatar
念毅掷
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有