refresh() -> invokeBeanFactoryPostProcessors()
refresh() -> invokeBeanFactoryPostProcessors()
调用各种BeanFactory
处理器,如:
解析占位符
${}
中对应属性值的替换工作
扩充
通常如果想对BeanFactory
中的数据进行修改时可以通过实现BeanFactoryPostProcessor
来进行实现
@FunctionalInterface
public interface BeanFactoryPostProcessor {void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
}
针对BeanFactory
同理,如果想要修改BeanDefinition
中的信息时可以实现BeanDefinitionRegistryPostProcessor
进行操作
public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor {void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException;
}
针对BeanDefinition,而BeanFactory已包含;
BeanDefinitionRegistry
的作用为对BeanDefinition的增删改查操作如果一个类实现了
BeanDefinitionRegistryPostProcessor
,那么他的postProcessBeanFactory()
方法可以跟其他的BeanFactoryPostProcessor
一起执行所有后置Registry的对象都是对前面名称对象的增删改查的操作
有关IOC中对象执行顺序的说明
PriorityOrdered > Ordered > 没有实现任何排序接口的对象
public interface PriorityOrdered extends Ordered {}public interface Ordered {int HIGHEST_PRECEDENCE = Integer.MIN_VALUE;int LOWEST_PRECEDENCE = Integer.MAX_VALUE;int getOrder();
}
invokeBeanFactoryPostProcessors()
实例化并且调用所有已经注册了的BeanFactoryPostProcessor,遵循指明的顺序
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {// 获取到当前应用程序上下文的beanFactoryPostProcessors变量的值,并且实例化调用执行所有已经注册的beanFactoryPostProcessorPostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());// Detect a LoadTimeWeaver and prepare for weaving, if found in the meantime// (e.g. through an @Bean method registered by ConfigurationClassPostProcessor)if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));}
}
getBeanFactoryPostProcessors()
默认情况下,通过此来获取已经注册的BFPP
(BeanFactoryPostProcessor),但是默认是空的,此处也可以将自定义的BFPP获取到
自定义BFPP
实现BFPP接口
import org.springframework.beans.BeansException; import org.springframework.beans.factory.config.BeanFactoryPostProcessor; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {@Overridepublic void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {System.out.println("自定义BeanFactoryPostProcessor");} }
将自定义BFPP注入到IOC容器或者自定义
ClassPathXmlApplicationContext
重写在getBeanFactoryPostProcessors()
调用之前的任意方法调用父类的addBeanFactoryPostProcessor()
进行BFPP
的注入,如:customizeBeanFactory()
import com.armin.self_bfpp.MyBeanFactoryPostProcessor; import org.springframework.beans.BeansException; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.beans.factory.support.DefaultListableBeanFactory; import org.springframework.context.support.ClassPathXmlApplicationContext;public class MyClassPathApplicationContext extends ClassPathXmlApplicationContext {public MyClassPathApplicationContext(String... configLocations) throws BeansException {super(configLocations);}@Overrideprotected void customizeBeanFactory(DefaultListableBeanFactory beanFactory) {super.addBeanFactoryPostProcessor(new MyBeanFactoryPostProcessor());super.customizeBeanFactory(beanFactory);} }
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors()
实例化调用执行所有已经注册的beanFactoryPostProcessor
public static void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {// Invoke BeanDefinitionRegistryPostProcessors first, if any.// 无论是什么情况,优先执行BeanDefinitionRegistryPostProcessors// 将已经执行过的BFPP存储在processedBeans中,防止重复执行Set<String> processedBeans = new HashSet<>();// 判断beanfactory是否是BeanDefinitionRegistry类型,此处是DefaultListableBeanFactory,实现了BeanDefinitionRegistry接口,所以为trueif (beanFactory instanceof BeanDefinitionRegistry) {// 类型转换BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;// 此处希望大家做一个区分,两个接口是不同的,BeanDefinitionRegistryPostProcessor是BeanFactoryPostProcessor的子集// BeanFactoryPostProcessor主要针对的操作对象是BeanFactory,而BeanDefinitionRegistryPostProcessor主要针对的操作对象是BeanDefinition// 存放BeanFactoryPostProcessor的集合List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();// 存放BeanDefinitionRegistryPostProcessor的集合List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();// 首先处理入参中的beanFactoryPostProcessors,遍历所有的beanFactoryPostProcessors,将BeanDefinitionRegistryPostProcessor// 和BeanFactoryPostProcessor区分开for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {// 如果是BeanDefinitionRegistryPostProcessorif (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {BeanDefinitionRegistryPostProcessor registryProcessor =(BeanDefinitionRegistryPostProcessor) postProcessor;// 直接执行BeanDefinitionRegistryPostProcessor接口中的postProcessBeanDefinitionRegistry方法registryProcessor.postProcessBeanDefinitionRegistry(registry);// 添加到registryProcessors,用于后续执行postProcessBeanFactory方法registryProcessors.add(registryProcessor);} else {// 否则,只是普通的BeanFactoryPostProcessor,添加到regularPostProcessors,用于后续执行postProcessBeanFactory方法regularPostProcessors.add(postProcessor);}}// Do not initialize FactoryBeans here: We need to leave all regular beans// uninitialized to let the bean factory post-processors apply to them!// Separate between BeanDefinitionRegistryPostProcessors that implement// PriorityOrdered, Ordered, and the rest.// 用于保存本次要执行的BeanDefinitionRegistryPostProcessorList<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();// First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.// 调用所有实现PriorityOrdered接口的BeanDefinitionRegistryPostProcessor实现类// 找到所有实现BeanDefinitionRegistryPostProcessor接口bean的beanNameString[] postProcessorNames =beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);// 遍历处理所有符合规则的postProcessorNamesfor (String ppName : postProcessorNames) {// 检测是否实现了PriorityOrdered接口if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {// 获取名字对应的bean实例,添加到currentRegistryProcessors中currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));// 将要被执行的BFPP名称添加到processedBeans,避免后续重复执行processedBeans.add(ppName);}}// 按照优先级进行排序操作sortPostProcessors(currentRegistryProcessors, beanFactory);// 添加到registryProcessors中,用于最后执行postProcessBeanFactory方法registryProcessors.addAll(currentRegistryProcessors);// 遍历currentRegistryProcessors,执行postProcessBeanDefinitionRegistry方法invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);// 执行完毕之后,清空currentRegistryProcessorscurrentRegistryProcessors.clear();// Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered.// 调用所有实现Ordered接口的BeanDefinitionRegistryPostProcessor实现类// 找到所有实现BeanDefinitionRegistryPostProcessor接口bean的beanName,// 此处需要重复查找的原因在于上面的执行过程中可能会新增其他的BeanDefinitionRegistryPostProcessorpostProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);for (String ppName : postProcessorNames) {// 检测是否实现了Ordered接口,并且还未执行过if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {// 获取名字对应的bean实例,添加到currentRegistryProcessors中currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));// 将要被执行的BFPP名称添加到processedBeans,避免后续重复执行processedBeans.add(ppName);}}// 按照优先级进行排序操作sortPostProcessors(currentRegistryProcessors, beanFactory);// 添加到registryProcessors中,用于最后执行postProcessBeanFactory方法registryProcessors.addAll(currentRegistryProcessors);// 遍历currentRegistryProcessors,执行postProcessBeanDefinitionRegistry方法invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);// 执行完毕之后,清空currentRegistryProcessorscurrentRegistryProcessors.clear();// Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear.// 最后,调用所有剩下的BeanDefinitionRegistryPostProcessorsboolean reiterate = true;while (reiterate) {reiterate = false;// 找出所有实现BeanDefinitionRegistryPostProcessor接口的类postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);// 遍历执行for (String ppName : postProcessorNames) {// 跳过已经执行过的BeanDefinitionRegistryPostProcessorif (!processedBeans.contains(ppName)) {// 获取名字对应的bean实例,添加到currentRegistryProcessors中currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));// 将要被执行的BFPP名称添加到processedBeans,避免后续重复执行processedBeans.add(ppName);reiterate = true;}}// 按照优先级进行排序操作sortPostProcessors(currentRegistryProcessors, beanFactory);// 添加到registryProcessors中,用于最后执行postProcessBeanFactory方法registryProcessors.addAll(currentRegistryProcessors);// 遍历currentRegistryProcessors,执行postProcessBeanDefinitionRegistry方法invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);// 执行完毕之后,清空currentRegistryProcessorscurrentRegistryProcessors.clear();}// Now, invoke the postProcessBeanFactory callback of all processors handled so far.// 调用所有BeanDefinitionRegistryPostProcessor的postProcessBeanFactory方法invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);// 最后,调用入参beanFactoryPostProcessors中的普通BeanFactoryPostProcessor的postProcessBeanFactory方法invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);} else {// Invoke factory processors registered with the context instance.// 如果beanFactory不归属于BeanDefinitionRegistry类型,那么直接执行postProcessBeanFactory方法invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);}// 到这里为止,入参beanFactoryPostProcessors和容器中的所有BeanDefinitionRegistryPostProcessor已经全部处理完毕,下面开始处理容器中// 所有的BeanFactoryPostProcessor// 可能会包含一些实现类,只实现了BeanFactoryPostProcessor,并没有实现BeanDefinitionRegistryPostProcessor接口// Do not initialize FactoryBeans here: We need to leave all regular beans// uninitialized to let the bean factory post-processors apply to them!// 找到所有实现BeanFactoryPostProcessor接口的类String[] postProcessorNames =beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);// Separate between BeanFactoryPostProcessors that implement PriorityOrdered,// Ordered, and the rest.// 用于存放实现了PriorityOrdered接口的BeanFactoryPostProcessorList<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();// 用于存放实现了Ordered接口的BeanFactoryPostProcessor的beanName// List<String> orderedPostProcessorNames = new ArrayList<>();List<BeanFactoryPostProcessor> orderedPostProcessor = new ArrayList<>();// 用于存放普通BeanFactoryPostProcessor的beanName// List<String> nonOrderedPostProcessorNames = new ArrayList<>();List<BeanFactoryPostProcessor> nonOrderedPostProcessorNames = new ArrayList<>();// 遍历postProcessorNames,将BeanFactoryPostProcessor按实现PriorityOrdered、实现Ordered接口、普通三种区分开for (String ppName : postProcessorNames) {// 跳过已经执行过的BeanFactoryPostProcessorif (processedBeans.contains(ppName)) {// skip - already processed in first phase above}// 添加实现了PriorityOrdered接口的BeanFactoryPostProcessor到priorityOrderedPostProcessorselse if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));}// 添加实现了Ordered接口的BeanFactoryPostProcessor的beanName到orderedPostProcessorNameselse if (beanFactory.isTypeMatch(ppName, Ordered.class)) {// orderedPostProcessorNames.add(ppName);orderedPostProcessor.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));} else {// 添加剩下的普通BeanFactoryPostProcessor的beanName到nonOrderedPostProcessorNames// nonOrderedPostProcessorNames.add(ppName);nonOrderedPostProcessorNames.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));}}// First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered.// 对实现了PriorityOrdered接口的BeanFactoryPostProcessor进行排序sortPostProcessors(priorityOrderedPostProcessors, beanFactory);// 遍历实现了PriorityOrdered接口的BeanFactoryPostProcessor,执行postProcessBeanFactory方法invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);// Next, invoke the BeanFactoryPostProcessors that implement Ordered.// 创建存放实现了Ordered接口的BeanFactoryPostProcessor集合// List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());// 遍历存放实现了Ordered接口的BeanFactoryPostProcessor名字的集合// for (String postProcessorName : orderedPostProcessorNames) {// 将实现了Ordered接口的BeanFactoryPostProcessor添加到集合中// orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));// }// 对实现了Ordered接口的BeanFactoryPostProcessor进行排序操作// sortPostProcessors(orderedPostProcessors, beanFactory);sortPostProcessors(orderedPostProcessor, beanFactory);// 遍历实现了Ordered接口的BeanFactoryPostProcessor,执行postProcessBeanFactory方法// invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);invokeBeanFactoryPostProcessors(orderedPostProcessor, beanFactory);// Finally, invoke all other BeanFactoryPostProcessors.// 最后,创建存放普通的BeanFactoryPostProcessor的集合// List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());// 遍历存放实现了普通BeanFactoryPostProcessor名字的集合// for (String postProcessorName : nonOrderedPostProcessorNames) {// 将普通的BeanFactoryPostProcessor添加到集合中// nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));// }// 遍历普通的BeanFactoryPostProcessor,执行postProcessBeanFactory方法// invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);invokeBeanFactoryPostProcessors(nonOrderedPostProcessorNames, beanFactory);// Clear cached merged bean definitions since the post-processors might have// modified the original metadata, e.g. replacing placeholders in values...// 清除元数据缓存(mergeBeanDefinitions、allBeanNamesByType、singletonBeanNameByType)// 因为后置处理器可能已经修改了原始元数据,例如,替换值中的占位符beanFactory.clearMetadataCache();
}
整个方法的大致执行流程
首先执行
beanFactory
调用addBeanFactoryPostProcessor
添加的BeanFactoryPostProcessor
如果该类为
BeanDefinitionRegistryPostProcessor
的实现先执行BeanDefinitionRegistryPostProcessor
中的postProcessBeanDefinitionRegistry
方法再将该实例放入集合中后续统一执行父接(BeanFactoryPostProcessor)口中的postProcessBeanFactory
方法从
BeanFactory
中获取BeanDefinitionRegistryPostProcessor
并且实现PriorityOrdered
接口的BeanName
,然后通过BeanFactory
中<T> T getBean(String name, Class<T> requiredType)
方法获取实例(该方法会调用实例化Bean
中的creatBean
方法),放入集合先统一执行postProcessBeanDefinitionRegistry
再将该对象放入另一个集合后续统一执行postProcessBeanFactory
方法再次重复第2点(不一样的地方:
PriorityOrdered
改为Ordered
)执行剩下的
BeanDefinitionRegistryPostProcessor
考虑可能存在执行上一步的时候在BeanDefinitionRegistryPostProcessor
对象中调用postProcessBeanDefinitionRegistry
会添加新的BeanDefinitionRegistryPostProcessor
对象此处会循环将所有的BeanDefinitionRegistryPostProcessor
执行完获取
BeanFactoryPostProcessor
类型的所有BeanName
根据是否实现PriorityOrdered
,Ordered
和没有实现任何排序接口的依次从前往后执行postProcessBeanFactory
方法
invokeBeanDefinitionRegistryPostProcessors()
调用给定BeanDefinitionRegistryPostProcessor Bean对象
private static void invokeBeanDefinitionRegistryPostProcessors(Collection<? extends BeanDefinitionRegistryPostProcessor> postProcessors, BeanDefinitionRegistry registry) {//遍历 postProcessorsfor (BeanDefinitionRegistryPostProcessor postProcessor : postProcessors) {//调用 postProcessor 的 postProcessBeanDefinitionRegistry以使得postProcess往registry注册BeanDefinition对象postProcessor.postProcessBeanDefinitionRegistry(registry);}
}
invokeBeanFactoryPostProcessors()
调用给定的BeanFactoryPostProcessor类型Bean对象
private static void invokeBeanFactoryPostProcessors(Collection<? extends BeanFactoryPostProcessor> postProcessors, ConfigurableListableBeanFactory beanFactory) {//遍历postProcessorsfor (BeanFactoryPostProcessor postProcessor : postProcessors) {//回调 BeanFactoryPostProcessor 的 postProcessBeanFactory 方法,使得每个postProcessor对象都可以对// beanFactory进行调整postProcessor.postProcessBeanFactory(beanFactory);}
}
测试从BeanFactory中根据类型获取到的BeanDefinitionRegisterPostProcessor在其中又添加新的BeanDefinitionRegisterPostProcessor执行结果
MyBeanDefinitionRegisterPostProcessor
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;public class MyBeanDefinitionRegisterPostProcessor implements BeanDefinitionRegistryPostProcessor {@Overridepublic void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {System.out.println("执行postProcessBeanDefinitionRegistry()--" + getClass().getName());BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(MySelfBeanDefinitionRegisterPostProcessor.class);builder.addPropertyValue("name", "armin");registry.registerBeanDefinition("mySelfBdrpp",builder.getBeanDefinition());}@Overridepublic void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {System.out.println("执行postProcessBeanFactory()--" + getClass().getName());}
}
MySelfBeanDefinitionRegisterPostProcessor
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;public class MySelfBeanDefinitionRegisterPostProcessor implements BeanDefinitionRegistryPostProcessor {private String name;public String getName() {return name;}public void setName(String name) {this.name = name;}@Overridepublic void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {System.out.println("执行postProcessBeanDefinitionRegistry()--" + getClass().getName());}@Overridepublic void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {System.out.println("执行postProcessBeanFactory()--" + getClass().getName());}
}
Test
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;public class Test {public static void main(String[] args) {ApplicationContext ac = new ClassPathXmlApplicationContext("armin-self-bdrpp.xml");}}
armin-self-bdrpp.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"><bean class="com.armin.self_bdrpp.MyBeanDefinitionRegisterPostProcessor"></bean></beans>
执行结果
> Task :spring-debug:Test.main()
执行postProcessBeanDefinitionRegistry()--com.armin.self_bdrpp.MyBeanDefinitionRegisterPostProcessor
执行postProcessBeanDefinitionRegistry()--com.armin.self_bdrpp.MySelfBeanDefinitionRegisterPostProcessor
执行postProcessBeanFactory()--com.armin.self_bdrpp.MyBeanDefinitionRegisterPostProcessor
执行postProcessBeanFactory()--com.armin.self_bdrpp.MySelfBeanDefinitionRegisterPostProcessorBUILD SUCCESSFUL in 2m 1s
refresh() -> invokeBeanFactoryPostProcessors()相关推荐
- http头部信息解析
HTTP(HyperTextTransferProtocol)是超文本传输协议的缩写,它用于传送WWW方式的数据,关于HTTP协议的详 细内容请参考RFC2616.HTTP协议采用了请求/响应模型.客 ...
- http协议头信息详解
注:此文复制而来,只为便于学习! 通常HTTP消息包括客户机向服务器的请求消息和服务器向客户机的响应消息.这两种类型的消息由一个起始行,一个或者多个头域,一个只是头域结束的空行和可 选的消息体组成.H ...
- HTTP协议(HyperText Transfer Protocol,超文本传输协议)
HTTP协议(HyperText Transfer Protocol,超文本传输协议)是因特网上应用最为广泛的一种网络传输协议,所有的WWW文件都必须遵守这个标准. HTTP是一个基于TCP/IP通信 ...
- SpringBoot(1.5.6.RELEASE)源码解析(一)
启动SpringBoot,需要在入口函数所在的类上添加@SpringBootApplication注解 1 @SpringBootApplication 2 public class Applicat ...
- HTTP协议SSL协议HTTPS协议
文章目录 1.HTTP协议 1.1.HTTP 简介 1.2.HTTP 消息结构 1.3.HTTP 请求方法 1.4.HTTP 响应头信息 1.5.HTTP 状态码 1.6.HTTP协议的优点与缺点 2 ...
- HTTP协议的头信息详解
HTTP协议的头信息详解 http://blog.csdn.net/guoguo1980/archive/2008/07/14/2649658.aspx HTTP协议的头信息详解 HTTP(Hyper ...
- ImportBeanDefinitionRegistrar向容器中注册bean
一.ImportBeanDefinitionRegistrar 我们先来看看ImportBeanDefinitionRegistrar是个什么鬼,点击进入ImportBeanDefinitionReg ...
- Java Servlet和JSP教程
http://www.bccn.net/article/web/jsp/jc/200409/72.html 简介 这是一个比较完整的Servlet.JSP教程,包含大量的实用资料和示例,仙人掌工作室倾 ...
- 最全的http头部信息分析(转载)
1.http 头信息详解 HTTP(HyperTextTransferProtocol)是超文本传输协议的缩写,它用于传送WWW方式的数据,关于HTTP协议的详细内容请参考RFC2616.HTTP协议 ...
最新文章
- oracle 连接池sql跟踪,实现SQLServer、MySQL和oracle数据库连接池
- HTML-语义类标签
- 搜狗浏览器也可以直接安装Chrome插件,太棒了
- C++笔记-shared_ptr与weak_ptr需要注意的地方
- 《数据库设计入门经典》读书笔记——第二章:工作场所中的数据库建模
- 最大化最小值 | | 最小化最大值
- Linux详解系列2- 这100条常见命令你都用过哪些?
- C# 在 webBrowser 光标处插入 html代码 .
- [鸟哥linux视频教程整理]03_03_bash特性详解续
- atitit 编程语言概念与原理
- atitit.重装系统需要备份的资料总结 o84..
- FontLab VI(字体制作软件)v6.1.4.7043中文版
- Google微软IBM能打败亚马逊AWS的理由很丰满,进展却骨感
- 个人业务存在的开票和个税问题,自然人代开核定征收解决
- 经典排序算法之--冒泡排序
- 如何实现Linux下的U盘(USB Mass Storage)驱动
- 电视K歌软件哪个好?这10款最火,最好用的电视K歌软件,赶紧收藏
- Linux: systemd 启动代码分析
- InnoDB——架构、日志、表和索引
- project 2016 显示、取消任务序号