文章目录
类的继承图
构造初始化
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。