Spring Core AnnotationConfigApplicationContext的构造

类的继承图

在这里插入图片描述

构造初始化

AnnotationConfigApplicationContext annotationConfigApplicationContext
				= new AnnotationConfigApplicationContext();

从AnnotationConfigApplicationContext的无参构造讲起。
Java中父子类构造方法调用、静态代码块、构造代码块调用逻辑。

1.DefaultResourceLoader
/**
	 * Create a new DefaultResourceLoader.
	 * <p>ClassLoader access will happen using the thread context class loader
	 * at the time of this ResourceLoader's initialization.
	 * @see java.lang.Thread#getContextClassLoader()
	 */
public DefaultResourceLoader() {
		this.classLoader = ClassUtils.getDefaultClassLoader();
	}

DefaultResourceLoader会创建一个默认的资源加载器。默认的为当前线程的类加载器,获取为null会最终取到bootstrap ClassLoader

@Nullable
	public static ClassLoader getDefaultClassLoader() {
		ClassLoader cl = null;
		try {
			cl = Thread.currentThread().getContextClassLoader();
		}
		catch (Throwable ex) {
			// Cannot access thread context ClassLoader - falling back...
		}
		if (cl == null) {
			// No thread context class loader -> use class loader of this class.
			cl = ClassUtils.class.getClassLoader();
			if (cl == null) {
				// getClassLoader() returning null indicates the bootstrap ClassLoader
				try {
					cl = ClassLoader.getSystemClassLoader();
				}
				catch (Throwable ex) {
					// Cannot access system ClassLoader - oh well, maybe the caller can live with null...
				}
			}
		}
		return cl;
	}
2 AbstractApplicationContext

抽象类AbstractApplicationContext相当于提供了应用上下文的模板方法,子类只需要实现或者覆盖父类即可。
类似的还有ReentrantLock,ReentrantReadWriteLock.WriteLock中的sync 继承AbstractQueuedSynchronizer。
AbstractApplicationContext的静态代码块及无参构造。

static {
		// Eagerly load the ContextClosedEvent class to avoid weird classloader issues
		// on application shutdown in WebLogic 8.1. (Reported by Dustin Woods.)
		ContextClosedEvent.class.getName();
	}
public AbstractApplicationContext() {
		this.resourcePatternResolver = getResourcePatternResolver();
	}
		public AbstractApplicationContext(@Nullable ApplicationContext parent) {
		this();
		setParent(parent);
	}

默认无参构造,提供了以classpath开头的通配符方式查询,否则会调用ResourceLoader的getResource方法来查找
this.resourcePatternResolver = new PathMatchingResourcePatternResolver(this);
PathMatchingResourcePatternResolver的静态代码块

static {
		try {
			// Detect Equinox OSGi (e.g. on WebSphere 6.1)
			Class<?> fileLocatorClass = ClassUtils.forName("org.eclipse.core.runtime.FileLocator",
					PathMatchingResourcePatternResolver.class.getClassLoader());
			equinoxResolveMethod = fileLocatorClass.getMethod("resolve", URL.class);
			logger.debug("Found Equinox FileLocator for OSGi bundle URL resolution");
		}
		catch (Throwable ex) {
			equinoxResolveMethod = null;
		}
	}

AbstractApplicationContext提供了有参构造会执行setParent,即为当前上下文设置父上下文。这个在SpringCloud Ribbon中有使用不同的客户端即使用的不同的ApplicationContext,并且设置当前ApplicationContext为父。

@RibbonClients({
        @RibbonClient(name = "SERVER-ORDER",configuration = OrderRuleConfig.class),
        @RibbonClient(name = "SERVER-POWER",configuration = PowerRuleConfig.class)
})

可以在代码中查看设计到parent的代码

protected void publishEvent(Object event, @Nullable ResolvableType eventType) {
... 省略中间代码
 可以看见 会传播监听事件到父上下文中。
if (this.parent != null) {
			if (this.parent instanceof AbstractApplicationContext) {
				((AbstractApplicationContext) this.parent).publishEvent(event, eventType);
			}
			else {
				this.parent.publishEvent(event);
			}
		}
}
protected void initMessageSource(){
		判断是否有父类且是一个分层级的messageSource,如果是将父容器的的messageSource设置到里边
		if (this.parent != null && this.messageSource instanceof HierarchicalMessageSource) {
			HierarchicalMessageSource hms = (HierarchicalMessageSource) this.messageSource;
			if (hms.getParentMessageSource() == null) {
				// Only set parent context as parent MessageSource if no parent MessageSource
				// registered already.
				hms.setParentMessageSource(getInternalParentMessageSource());
			}
		}
}
3 GenericApplicationContext

GenericApplicationContext 无参构造中初始化了默认的BeanFactory:DefaultListableBeanFactory

public GenericApplicationContext() {
		this.beanFactory = new DefaultListableBeanFactory();
	}
	public GenericApplicationContext(DefaultListableBeanFactory beanFactory, ApplicationContext parent) {
		this(beanFactory);
		setParent(parent);
	}
	@Override
	public void setParent(@Nullable ApplicationContext parent) {
		super.setParent(parent);
		this.beanFactory.setParentBeanFactory(getInternalParentBeanFactory());
	}

GenericApplicationContext 的有参构造中同样使用了setParent方法,此方法会设置父BeanFactory。
GenericApplicationContext 使用到的getBean方法即是使用的beanFactory.getBean方法。
GenericApplicationContext 的实现类中常用的有

  • GenericWebApplicationContext servletContext
  • AnnotationConfigApplicationContext 基于注解会初始化reader – AnnotatedBeanDefinitionReader scanner
  • StaticApplicationContext
  • GenericXmlApplicationContext 基于xml方式的reader – XmlBeanDefinitionReader
4 AnnotationConfigApplicationContext
public AnnotationConfigApplicationContext() {
		/**
		 * 父类的构造方法
		 * 创建一个读取注解的Bean定义读取器
		 */
		this.reader = new AnnotatedBeanDefinitionReader(this);
		//可以用来扫描包或者类,继而转换成bd
		//但是实际上我们扫描包工作不是scanner这个对象来完成的
		//是spring自己new的一个ClassPathBeanDefinitionScanner
		//这里的scanner仅仅是为了程序员能够在外部调用AnnotationConfigApplicationContext对象的scan方法
		this.scanner = new ClassPathBeanDefinitionScanner(this);
	}
		public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment) {
		Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
		Assert.notNull(environment, "Environment must not be null");
		this.registry = registry;
		this.conditionEvaluator = new ConditionEvaluator(registry, environment, null);
		AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
	}

无参构造会初始化reader和scanner
readr 中的ConditionEvaluator 是用于计算带有Conditon注解的类是否应该忽略生成BeanDefinition。
AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
会初始化最重要的的6个BeanDefinition,后面能够把所有的Bean加入到Bean容器全靠这些processor。
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值