Spring Bean XML 配置解析
- Spring Bean XML 配置解析
- **配置示例代码**
- 原理解析
- 1. ResourceLoader 资源加载
- 2. DocumentLoader XML Document 加载器
- 3. BeanDefinitionReader Bean 定义阅读器
- 4. BeanDefinitionDocumentReader Bean 定义Document 阅读器
- 5. BeanDefinitionParserDelegate Bean 定义解析委托类
- 6. NamespaceHandlerResolver 命名空间处理器的处理者
- 7. NamespaceHandler 命名空间处理器
- 8. BeanDefinitionParser Bean 定义解析器
- 9. ParserContext 解析上下文
Spring Bean 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" xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<!-- 启动注解驱动的spring MVC功能,注册请求url和注解POJO类方法的映射-->
<mvc:annotation-driven/>
<context:component-scan base-package="com.zxguan.template"/>
<!--静态文件-->
<mvc:default-servlet-handler/>
<!-- 对模型视图名称的解析,在请求时模型视图名称添加前后缀 -->
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
<property name="prefix" value="view/"/> <!-- 前缀 -->
<property name="suffix" value=".jsp"/> <!-- 后缀 -->
</bean>
</beans>
原理解析
1. ResourceLoader 资源加载
ResourcePatternResolver(PathMatchingResourcePatternResolver): 资源表达式配置处理,负责资源加载解析为 Resource
2. DocumentLoader XML Document 加载器
DefaultDocumentLoader:XML Document 默认加载实现,解析为 Document
解析结构(对应配置示例代码)
Document(配置文件)
- Element(<beans></beans>)
- Node(<bean></bean>)
- Node(<import/>)
- Node(<alias/>)
- Node(<beans/>)
- Node(<mvc:annotation-driven/>)
- Node(<context:component-scan/>)
- Node(<mvc:default-servlet-handler/>)
- ......
- ......
- ......
3. BeanDefinitionReader Bean 定义阅读器
XmlBeanDefinitionReader:XML 文件 Bean 定义阅读器,解析成
Document
,且解析后每个节点都会有其对应的命名空间名称属性
4. BeanDefinitionDocumentReader Bean 定义Document 阅读器
DefaultBeanDefinitionDocumentReader:默认的 BeanDefinitionDocumentReader 实现,可能后续出现其他 Document 阅读者
5. BeanDefinitionParserDelegate Bean 定义解析委托类
BeanDefinitionParserDelegate:负责具体的 XML 配置解析,即 Document 中内容的解析。此处定义了 Spring XML Bean 配置的所有配置项属性及解析,
包含以下几类:
<import resource="datasource.xml"/>
<alias name="resourceHolder" alias="resourceHolder1"/>
<bean id="testController" class="com.zxguan.template.controller.TestController"/>
<beans></beans>
Spring 关于命名空间的规定:
Spring 命名空间 | 类别 |
---|---|
http://www.springframework.org/schema/beans | 默认 |
除 http://www.springframework.org/schema/beans 之外的命名空间,如: http://www.springframework.org/schema/context 、http://www.springframework.org/schema/mvc 等等 | 自定义 |
判断节点中命名空间是
默认
还是自定义
。如果是自定义则根据命名空间查找NamespaceHandler
对应的实现类,进而解析配置信息。
protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
if (delegate.isDefaultNamespace(root)) {
NodeList nl = root.getChildNodes();
for (int i = 0; i < nl.getLength(); i++) {
Node node = nl.item(i);
if (node instanceof Element) {
Element ele = (Element) node;
if (delegate.isDefaultNamespace(ele)) {
parseDefaultElement(ele, delegate);
}
else {
delegate.parseCustomElement(ele);
}
}
}
}
else {
delegate.parseCustomElement(root);
}
}
6. NamespaceHandlerResolver 命名空间处理器的处理者
默认:DefaultNamespaceHandlerResolver:负责
NamespaceHandler
的选择
debug 调试时, IDEA 会开启另一个线程调用 DefaultNamespaceHandlerResolver 的 toString 方法,进而初
始化 handlerMappings,此时会发现打断点无法进入到初始化程序中,就是这个原因。
对于重写了 toString 方法的类,在用 Debug 调试时 IDEA 会另起一个线程调用 toString 方法,toString 的调用过程,IDEA 无法监听到
7. NamespaceHandler 命名空间处理器
NamespaceHandlerSupport:NamespaceHandler 的抽象实现,负责除 BeanDefinitionParserDelegate 中默认解析不能处理的标签的解析处理。其子类负责注册命名空间名与对应解析类映射,如:
public class MvcNamespaceHandler extends NamespaceHandlerSupport {
@Override
public void init() {
registerBeanDefinitionParser("annotation-driven", new AnnotationDrivenBeanDefinitionParser());
registerBeanDefinitionParser("default-servlet-handler", new DefaultServletHandlerBeanDefinitionParser());
registerBeanDefinitionParser("interceptors", new InterceptorsBeanDefinitionParser());
registerBeanDefinitionParser("resources", new ResourcesBeanDefinitionParser());
registerBeanDefinitionParser("view-controller", new ViewControllerBeanDefinitionParser());
registerBeanDefinitionParser("redirect-view-controller", new ViewControllerBeanDefinitionParser());
registerBeanDefinitionParser("status-controller", new ViewControllerBeanDefinitionParser());
registerBeanDefinitionParser("view-resolvers", new ViewResolversBeanDefinitionParser());
registerBeanDefinitionParser("tiles-configurer", new TilesConfigurerBeanDefinitionParser());
registerBeanDefinitionParser("freemarker-configurer", new FreeMarkerConfigurerBeanDefinitionParser());
registerBeanDefinitionParser("groovy-configurer", new GroovyMarkupConfigurerBeanDefinitionParser());
registerBeanDefinitionParser("script-template-configurer", new ScriptTemplateConfigurerBeanDefinitionParser());
registerBeanDefinitionParser("cors", new CorsBeanDefinitionParser());
}
}
SecurityNamespaceHandler
:负责spring-security
配置解析,位于spring-security-config
包中,示例配置如下:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:security="http://www.springframework.org/schema/security"
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 http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd">
<security:http pattern="/statics/**" security="none"/>
<security:http auto-config="true" use-expressions="true">
<security:intercept-url pattern="/login.do" access="isAnonymous()"/>
<security:intercept-url pattern="/register.do" access="isAnonymous()"/>
<security:intercept-url pattern="/registerusers.do" access="isAnonymous()"/>
<security:intercept-url pattern="/useradd.do" access="isAnonymous()"/>
<security:intercept-url pattern="/admins/**" access="hasRole('ROLE_ADMIN')"/>
<security:intercept-url pattern="/**" access="hasRole('ROLE_USER')"/>
<security:csrf disabled="false" token-repository-ref="cookieCsrfTokenRepository" />
<security:form-login login-page="/login.do" login-processing-url="/login" username-parameter="username" password-parameter="password" authentication-failure-url="/login.do?error=true" />
<security:logout invalidate-session="true" logout-url="/logout" logout-success-url="/login.do"/>
<security:http-basic />
<security:remember-me data-source-ref="dataSource" key="youkey" remember-me-parameter="remember-me"/>
<security:session-management>
<security:concurrency-control />
</security:session-management>
</security:http>
<security:authentication-manager>
<!--静态添加的用户登录信息-->
<!--<security:authentication-provider>
<security:user-service>
<security:user name="admin" password="admin123" authorities="ROLE_USER,ROLE_ADMIN"/>
<security:user name="user" password="user123" authorities="ROLE_USER"/>
</security:user-service>
</security:authentication-provider>-->
<security:authentication-provider>
<security:password-encoder ref="bCryptPasswordEncoder"/>
<security:jdbc-user-service id="userDetailsService" data-source-ref="dataSource"
users-by-username-query="SELECT username,password,enabled FROM users WHERE username=?"
authorities-by-username-query="SELECT u.username as username,r.rolename as authority FROM users u join userrole ur on u.userid=ur.userid join roles r on r.roleid=ur.roleid WHERE u.username=?"/>
</security:authentication-provider>
</security:authentication-manager>
<bean id="bCryptPasswordEncoder" class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder"/>
<bean id="daoAuthenticationProvider" class="org.springframework.security.authentication.dao.DaoAuthenticationProvider">
<property name="hideUserNotFoundExceptions" value="false"/>
<property name="userDetailsService" ref="userDetailsService"/>
<property name="passwordEncoder" ref="bCryptPasswordEncoder"/>
</bean>
<bean id="cookieCsrfTokenRepository" class="org.springframework.security.web.csrf.CookieCsrfTokenRepository">
<property name="cookieHttpOnly" value="false"/>
</bean>
</beans>
8. BeanDefinitionParser Bean 定义解析器
如:DefaultServletHandlerBeanDefinitionParser:负责 XML 中
<mvc:default-servlet-handler/>
的解析
9. ParserContext 解析上下文
负责提供一些解析所需用到的上下参数