周日处理一个spring-security的问题。顺带把spring的类加载机制和spring的security也看了一遍。
觉得spring的整个设计还是蛮有意思的。用的spring是4.3.18,后续用到的源码也都是这个版本的。
先看spring的加载机制。
spring对象的管理生成是通过BeanFactroy来生成的,目前比较常用的有
BeanFactroy
最基础的 BeanFactory, 提供了根据 name , type 等获取一个 bean 对象的能力
ListableBeanFactory
继承 BeanFactroy, 额外提供了列出所有bean对象的能力
HierarchialBeanFacotry
继承BeanFactroy,额外使了 factory 拥有一个parent factory的能力, 可以存在层级关系
SingletonbeanRegistry
提供了单例对象缓存的能力
AutowireCapableBeanFacory
继承 BeanFactroy, 提供了在创建对象时, 通过set方式给 bean 初始化 autowired 或者声明了 dependon 的成员
ConfigurableBeanFactory
继承 ListableBeanFactory 和 HierarchialBeanFacotry, 给 factory 提供了很多配置的方法, 比如设置 BeanPostProcessor
AliasRegistry
支持了多个别名
我们的项目中使用的是ListableBeanFactory,更具体的实现类是 XmlBeanFactory(这个类在4.3.18版本中已经不推荐使用) 。XmlBeanFactory同时是ListableBeanFactory的子类。
因为系统初始化是通过xml,所以xml只处理那些在xml中定义的bean对象,那些通过标注生成的对象是通过AutowireCapableBeanFacory来处理的,这里不展开。
XmlBeanFactory对于spring的加载是通过构造函数来做初始化工作的。详细如下:
/** * Create a new XmlBeanFactory with the given input stream, * which must be parsable using DOM. * @param resource XML resource to load bean definitions from * @param parentBeanFactory parent bean factory * @throws BeansException in case of loading or parsing errors */ public XmlBeanFactory(Resource resource, BeanFactory parentBeanFactory) throws BeansException { super(parentBeanFactory); this.reader.loadBeanDefinitions(resource); }
这个的Resource 就是classpath中的applicationContext.xml 文件。
通过成员变量来读取定义的resource
private final XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(this); XmlBeanDefinitionReader 的加载applicationContext.xml文件的逻辑 public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException { try { InputStream inputStream = encodedResource.getResource().getInputStream(); try { InputSource inputSource = new InputSource(inputStream); if (encodedResource.getEncoding() != null) { inputSource.setEncoding(encodedResource.getEncoding()); } return doLoadBeanDefinitions(inputSource, encodedResource.getResource()); } finally { inputStream.close(); } } }
中间又见过了多次的调用
loadBeanDefinitions -> doLoadBeanDefinitions -> doLoadDocument -> registerBeanDefinitions -> org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader#registerBeanDefinitions
最终真正解析xml的是DefaultBeanDefinitionDocumentReader 这个类的doRegisterBeanDefinitions 方法来处理。
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)) { //非xmlns定义的handler parseDefaultElement(ele, delegate); } else { //常用的handler delegate.parseCustomElement(ele); } } } } else { delegate.parseCustomElement(root); } }
在解析xml的过程中跟根据xml头部的ns定义,来获取对应的handler。
xml头部的xmlns 在parseDefaultElement方法中会被抽象成handler。 <beans xmlns="http://www.springframework.org/schema/beans" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:task="http://www.springframework.org/schema/task" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task.xsd">
xml中的每一个元素会被解析为 Element,常见的Element例如
<aop:aspectj-autoproxy />
<task:annotation-driven/>
<context:annotation-config/>
<aop:config proxy-target-class=”true”/>
每一个Element都会有对应的BeanDefinitionParserDelegate来处理。
BeanDefinitionParserDelegate做的事情就是把 对于的Element找到对应xmlns中定义的handler来处理
public BeanDefinition parseCustomElement(Element ele, BeanDefinition containingBd) { String namespaceUri = getNamespaceURI(ele); NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri); if (handler == null) { error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", ele); return null; } return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd)); }
NamespaceHandler的handler有如图所示:
每一个handler就是把对应的element解析为BeanDefinition 对象来做初始化。到此为止 XmlBeanFactory的工作已经完成了。
由于继承之DefaultListableBeanFactory,其他工作都是在DefaultListableBeanFactory中处理的。
DefaultListableBeanFactory在preInstantiateSingletons来做类的前置工作。 public void preInstantiateSingletons() throws BeansException { List<String> beanNames = new ArrayList<String>(this.beanDefinitionNames); // Trigger initialization of all non-lazy singleton beans... for (String beanName : beanNames) { RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName); if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) { if (isFactoryBean(beanName)) { //真正的初始化bean。 final FactoryBean<?> factory = (FactoryBean<?>) getBean(FACTORY_BEAN_PREFIX + beanName); boolean isEagerInit; if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) { isEagerInit = AccessController.doPrivileged(new PrivilegedAction<Boolean>() { @Override public Boolean run() { return ((SmartFactoryBean<?>) factory).isEagerInit(); } }, getAccessControlContext()); } else { isEagerInit = (factory instanceof SmartFactoryBean && ((SmartFactoryBean<?>) factory).isEagerInit()); } if (isEagerInit) { getBean(beanName); } } else { getBean(beanName); } } } }
getBean 又经过了
org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean
org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#getSingleton(java.lang.String, org.springframework.beans.factory.ObjectFactory<?>)
try {
//正常的创建对象
singletonObject = singletonFactory.getObject();
newSingleton = true;
}
到此为止 通过applicationContext.xml的配置文件加载及其中的bean加载已经完成。
总结的说:
主要通过XmlBeanFactory 来加载类,xml头部的xmlns定义了xml中各种element的处理类。最终的对象初始化是通过各种继承关系中的DefaultSingletonBeanRegistry来处理的。
工程类对于xml加载的继承体系是
XmlBeanFactory -> DefaultListableBeanFactory -> AbstractAutowireCapableBeanFactory -> AbstractBeanFactory -> FactoryBeanRegistrySupport -> DefaultSingletonBeanRegistry -> SimpleAliasRegistry -> AliasRegistry
0 条评论。