Spring Ioc容器読書ノート
8662 ワード
Ioc容器初期化プロセス< Ioc初期化の入り口はrefsh方法です. Resource位置付け(Resource Loaderモジュールが担当する) BenDefinitionをロードし、解析を行います.定義されたビームをロードし、Ioc容器内部のデータ構造に解析します.このBeanDefinitionを通じて、Ioc容器はBeanの管理を実現します. BenDefinition登録します.このプロセスはBeanDefinitionRegistryインターフェースを呼び出すことによって達成される.その本質は、解析されたBeanDefinitionをIoc容器のHashMapに入れることである.
BeanDefinitionの登録は、HashMapにBenDefinitionを入れるだけで完了します.依存の注入は、Ioc容器が起動するときに行われるものではない.ゲームビーンの実例の時だけです.
依存注入をトリガします.この二つは独立の過程です. BenDefinition Resource位置決め 表示クラスAbstract BenDefinitionReader: BenDefinitionのロードと解析 私たちはrefreshに戻ってきて、ロードを見に来ました.
Default BeanDefinitionDcument Reader類に入ってみます. BenDefinition登録
public FileSystemXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent)
throws BeansException {
super(parent);
setConfigLocations(configLocations);
if (refresh) {
refresh();
}
}
このrefresh方法はIoc容器の正式な起動を示しています.その起動は以下の3つのステップに分けられます. //DefaultListableBeanFactory
// Map of bean definition objects, keyed by bean name
private final Map <String,BeanDefinition> beanDefinitionMap = new ConcurrentHashMap <String,BeanDefinition>();
PS:ここではビーンDefinitionの登録とビーン依存注入の違いを強調します.BeanDefinitionの登録は、HashMapにBenDefinitionを入れるだけで完了します.依存の注入は、Ioc容器が起動するときに行われるものではない.ゲームビーンの実例の時だけです.
依存注入をトリガします.この二つは独立の過程です.
public int loadBeanDefinitions(String location, Set
<Resource> actualResources) throws BeanDefinitionStoreException {
ResourceLoader resourceLoader = getResourceLoader();
if (resourceLoader == null) {
//...
}
if (resourceLoader instanceof ResourcePatternResolver) {
// Resource pattern matching available.
try {
Resource[] resources = ((ResourcePatternResolver) resourceLoader).getResources(location);
int loadCount = loadBeanDefinitions(resources);
if (actualResources != null) {
...
}
}
return loadCount;
}
catch (IOException ex) {
//...
}
}
else {
//....
}
}
キーはロカションによってResourceの場所を決めます.どうぞご覧ください. public Resource[] getResources(String locationPattern) throws IOException {
Assert.notNull(locationPattern, "Location pattern must not be null");
if (locationPattern.startsWith(CLASSPATH_ALL_URL_PREFIX)) {
// a class path resource (multiple resources for same name possible)
if (getPathMatcher().isPattern(locationPattern.substring(CLASSPATH_ALL_URL_PREFIX.length()))) {
// a class path resource pattern
return findPathMatchingResources(locationPattern);
}
else {
// all class path resources with the given name
return findAllClassPathResources(locationPattern.substring(CLASSPATH_ALL_URL_PREFIX.length()));
}
}
else {
// Only look for a pattern after a prefix here
// (to not get fooled by a pattern symbol in a strange prefix).
int prefixEnd = locationPattern.indexOf(":") + 1;
if (getPathMatcher().isPattern(locationPattern.substring(prefixEnd))) {
// a file pattern
return findPathMatchingResources(locationPattern);
}
else {
// a single resource with the given name
return new Resource[] {getResourceLoader().getResource(locationPattern)};
}
}
}
ここで、上のclassipath*:パスと:先頭のパスの下のResourceが見つかりました. public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing.
prepareRefresh();
// Tell the subclass to refresh the internal bean factory.
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
prepareBeanFactory(beanFactory);
try {
// Allows post-processing of the bean factory in context subclasses.
postProcessBeanFactory(beanFactory);
// Invoke factory processors registered as beans in the context.
invokeBeanFactoryPostProcessors(beanFactory);
// Register bean processors that intercept bean creation.
registerBeanPostProcessors(beanFactory);
// Initialize message source for this context.
initMessageSource();
// Initialize event multicaster for this context.
initApplicationEventMulticaster();
// Initialize other special beans in specific context subclasses.
onRefresh();
// Check for listener beans and register them.
registerListeners();
// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);
// Last step: publish corresponding event.
finishRefresh();
}
catch (BeansException ex) {
// Destroy already created singletons to avoid dangling resources.
destroyBeans();
// Reset 'active' flag.
cancelRefresh(ex);
// Propagate exception to caller.
throw ex;
}
}
}
上の全体refresh方法はコンピュータシステムの再起動と同じである.私たちは簡単なバージョンのロードを見ます.Xml BenFactoryからの public XmlBeanFactory(Resource resource, BeanFactory parentBeanFactory) throws BeansException {
super(parentBeanFactory);
this.reader.loadBeanDefinitions(resource);
}
はXml BeanDefinitionReaderのに入ります. public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
Assert.notNull(encodedResource, "EncodedResource must not be null");
if (logger.isInfoEnabled()) {
logger.info("Loading XML bean definitions from " + encodedResource.getResource());
}
Set<EncodedResource> currentResources = this.resourcesCurrentlyBeingLoaded.get();
if (currentResources == null) {
currentResources = new HashSet<EncodedResource>(4);
this.resourcesCurrentlyBeingLoaded.set(currentResources);
}
if (!currentResources.add(encodedResource)) {
throw new BeanDefinitionStoreException(
"Detected cyclic loading of " + encodedResource + " - check your import definitions!");
}
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();
}
}
catch (IOException ex) {
//....
}
}
はまた入ります.protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
throws BeanDefinitionStoreException {
try {
int validationMode = getValidationModeForResource(resource);
Document doc = this.documentLoader.loadDocument(
inputSource, getEntityResolver(), this.errorHandler, validationMode, isNamespaceAware());
return registerBeanDefinitions(doc, resource);
}
catch (BeanDefinitionStoreException ex) {
//..
}
}
public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
documentReader.setEnvironment(this.getEnvironment());
int countBefore = getRegistry().getBeanDefinitionCount();
documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
return getRegistry().getBeanDefinitionCount() - countBefore;
}
上でXmlのプロファイルをメモリに読み込んでXml DcumentにしてBenDefinitionDcuntReaderに渡してこのDcumentを解析します.Default BeanDefinitionDcument Reader類に入ってみます.
private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
importBeanDefinitionResource(ele);
}
else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
processAliasRegistration(ele);
}
else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
processBeanDefinition(ele, delegate);
}
else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
// recurse
doRegisterBeanDefinitions(ele);
}
}
これで、タグの解析が始まります.