曹工说Spring Boot源码(1)-- Bean Definition到底是什么,附spring思维导图分享
曹工说Spring Boot源码(2)-- Bean Definition到底是什么,咱们对着接口,逐个方法讲解
曹工说Spring Boot源码(3)-- 手动注册Bean Definition不比游戏好玩吗,我们来试一下
曹工说Spring Boot源码(4)-- 我是怎么自定义ApplicationContext,从json文件读取bean definition的?
曹工说Spring Boot源码(5)-- 怎么从properties文件读取bean
曹工说Spring Boot源码(6)-- Spring怎么从xml文件里解析bean的
曹工说Spring Boot源码(7)-- Spring解析xml文件,到底从中得到了什么(上)
曹工说Spring Boot源码(8)-- Spring解析xml文件,到底从中得到了什么(util命名空间)
工程代码地址 思维导图地址
工程结构图:
概要先给大家看看spring支持的xml配置,我列了个表格如下:
namespace elementutil constant、property-path、list、set、map、properties
context property-placeholder、property-override、annotation-config、component-scan、load-time-weaver、spring-configured、mbean-export、mbean-server
beans import、bean、alias
task annotation-driven、scheduler、scheduled-tasks、executor
cache advice、annotation-driven
aop config、scoped-proxy、aspectj-autoproxy
我题目的意思是,spring在解析每个不同的xml元素时,其实是有共性的。所有这些元素的解析器,都实现了BeanDefinitionParser。这个接口只有一个方法,作用就是解析元素时,根据元素的配置,来收集beanDefinition,正所谓:条条大道通罗马,各种xml配置元素,各种注解配置,就是那些大道,罗马是什么?
就是beanDefinition。
从第一篇到现在,已经第9篇了,我们还在讲bean definition,其实就是因为,只有深刻地理解了它,后面才能更方便地理解spring boot,理解configuration注解,理解enable,理解自动装配。
好了,切入本篇,本篇要讲解的xml元素是context命名空间里的。
context:property-placeholder 用法 <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans "> <context:property-placeholder location="classpath*:application.properties"/> <bean> <property value="${name}"/> </bean> </beans> @Data public class TestPropertiesVO { private String name; } #application.properties name: Phil测试代码:
package org.springframework.contextnamespace; import com.alibaba.fastjson.JSONObject; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.util.MyFastJson; import java.util.List; import java.util.Map; @Slf4j public class TestPropertyPlaceholder { public static void main(String[] args) { ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext( new String[]{"classpath:context-namespace-test-property-holder.xml"},false); context.refresh(); Map<String, Object> map = context.getDefaultListableBeanFactory().getAllSingletonObjectMap(); log.info("singletons:{}", JSONObject.toJSONString(map)); List<BeanDefinition> list = context.getBeanFactory().getBeanDefinitionList(); MyFastJson.printJsonStringForBeanDefinitionList(list); // 获取该bean,打印 Object bean = context.getBean(TestPropertiesVO.class); System.out.println("bean:" + bean); } }输出如下:
bean:TestPropertiesVO(name=Phil)如果我们修改xml:
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans "> //注释之,看看会怎样 <!--<context:property-placeholder location="classpath*:application.properties"/>--> <bean> <property value="${name}"/> </bean> </beans>输出如下:
bean:TestPropertiesVO(name=${name})可以看到,这样子呢,就没法解析到properties中的值了。
等价用法 <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans "> <!--<context:property-placeholder location="classpath*:application.properties"/>--> // 这个配置方式,和上面那个,效果其实是一样的;上面那个,是对下边这种的封装 <bean> <property> <list> <value>classpath:application.properties</value> </list> </property> </bean> <bean> <property value="${name}"/> </bean> </beans> 元素解析