springboot源码----真正的应用上下文(AnnotationConfigServletWebServerApplicationContext)

首先看一下类的注释和翻译

/**
 * {@link ServletWebServerApplicationContext} that accepts annotated classes as input - in
 * particular {@link org.springframework.context.annotation.Configuration @Configuration}
 * -annotated classes, but also plain {@link Component @Component} classes and JSR-330
 * compliant classes using {@code javax.inject} annotations. Allows for registering
 * classes one by one (specifying class names as config location) as well as for classpath
 * scanning (specifying base packages as config location).
 * <p>
 * Note: In case of multiple {@code @Configuration} classes, later {@code @Bean}
 * definitions will override ones defined in earlier loaded files. This can be leveraged
 * to deliberately override certain bean definitions via an extra Configuration class.
 *
 * @author Phillip Webb
 * @see #register(Class...)
 * @see #scan(String...)
 * @see ServletWebServerApplicationContext
 * @see AnnotationConfigWebApplicationContext
 */
中文:
ServletWebServerApplicationContext接受带注释的类(特别是@Configuration带注释的类)作为输入,但也可以使用javax.inject注释将普通的@Component类和符合JSR-330的类作为输入。
允许一对一注册类(将类名指定为配置位置),以及进行类路径扫描(将基本包指定为配置位置)。
注意:如果有多个@Configuration类,则以后的@Bean定义将覆盖在先前加载的文件中定义的定义。可以利用此属性通过一个额外的Configuration类来故意覆盖某些Bean定义。

类图继承关系如下:

类图上发现,它既是BeanFactory,又是BeanDefinitionRegistry,还是ApplicationEventPublisher,  整个spring所存放的资源,几乎都在这里了。放在下面讲解。

何时创建了这个ApplicationContext呢?

SpringApplication类中的run方法中调用

context = createApplicationContext(); 

就是通过反射,调用了AnnotationConfigServletWebServerApplicationContext的无参构造方法

    /**
	 * Create a new {@link AnnotationConfigServletWebServerApplicationContext} that needs
	 * to be populated through {@link #register} calls and then manually
	 * {@linkplain #refresh refreshed}.
	 */
    //springboot创建ApplicationContext的时候就是通过反射,调用的这个构造方法
	public AnnotationConfigServletWebServerApplicationContext() {
		this.reader = new AnnotatedBeanDefinitionReader(this);
		this.scanner = new ClassPathBeanDefinitionScanner(this);
	}

1. 在初始化父类GenericApplicationContext的时候,创建了IOC极重要的BeanFactory---DefaultListableBeanFactory

	/**
	 * Create a new GenericApplicationContext.
	 * @see #registerBeanDefinition
	 * @see #refresh
	 */
	public GenericApplicationContext() {
		this.beanFactory = new DefaultListableBeanFactory();
	}

2. 构造方法中,初始化了AnnotatedBeanDefinitionReader和ClassPathBeanDefinitionScanner,(这两个类内部初始化了哪些东西,此处不叙)

3. ApplicationContext怎么还是BeanDefinitionRegistry呢?(先说答案,初始化了DefaultListableBeanFactory,BeanDefinitionRegistry自然就有了)

  3.1 首先看BeanDefinitionRegistry是什么

public interface BeanDefinitionRegistry extends AliasRegistry {

	void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
			throws BeanDefinitionStoreException;

	void removeBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;

	BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;

	boolean containsBeanDefinition(String beanName);

	String[] getBeanDefinitionNames();

	int getBeanDefinitionCount();

	boolean isBeanNameInUse(String beanName);

}

  可见,BeanDefinitionRegistry是用来注册BeanDefinition的,多说一句,所有的BeanDefinition最终都是在BeanFactory  (DefaultListableBeanFactory的beanDefinitionMap属性)里存放,

  3.2 这些接口方法在ApplicationContext是在哪里实现的呢?

     a) 从类图上看出AnnotationConfigServletWebServerApplicationContext父类GenericApplicationContext继承BeanDefinitionRegistry接口,

     b) 且GenericApplicationContext 并非抽象类,故而必须在此类中实现接口中的方法。实现方式如下:

    @Override
	public void removeBeanDefinition(String beanName) throws NoSuchBeanDefinitionException {
		this.beanFactory.removeBeanDefinition(beanName);
	}
	@Override
	public BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException {
		return this.beanFactory.getBeanDefinition(beanName);
	}
	@Override
	public boolean isBeanNameInUse(String beanName) {
		return this.beanFactory.isBeanNameInUse(beanName);
	}
	@Override
	public void registerAlias(String beanName, String alias) {
		this.beanFactory.registerAlias(beanName, alias);
	}
	@Override
	public void removeAlias(String alias) {
		this.beanFactory.removeAlias(alias);
	}
	@Override
	public boolean isAlias(String beanName) {
		return this.beanFactory.isAlias(beanName);
	}

     c) 由此可见,AnnotationConfigServletWebServerApplicationContext父类继承BeanDefinitionRegistry,并最终是调用了beanFactory的相关方法来实现的。

4. ApplicationContext怎么还是BeanFactory呢?

    4.1 首先看一下BeanFactory是什么

public interface BeanFactory {
	String FACTORY_BEAN_PREFIX = "&";
	Object getBean(String name) throws BeansException;
	Object getBean(String name, Object... args) throws BeansException;
	<T> T getBean(Class<T> requiredType) throws BeansException;
	<T> T getBean(Class<T> requiredType, Object... args) throws BeansException;
	<T> ObjectProvider<T> getBeanProvider(ResolvableType requiredType);
	boolean containsBean(String name);
	boolean isSingleton(String name) throws NoSuchBeanDefinitionException;
	boolean isPrototype(String name) throws NoSuchBeanDefinitionException;
	boolean isTypeMatch(String name, ResolvableType typeToMatch) throws NoSuchBeanDefinitionException;
	boolean isTypeMatch(String name, Class<?> typeToMatch) throws NoSuchBeanDefinitionException;
	@Nullable
	Class<?> getType(String name) throws NoSuchBeanDefinitionException;
	String[] getAliases(String name);
}

可见BeanFactory是用来获取Bean对象,检查Bean对象等操作

 4.2 这些接口方法在ApplicationContext是在哪里实现的呢?

AnnotationConfigServletWebServerApplicationContext的父类中抽象类AbstractApplicationContext 实现了BeanFactory接口中的方法,

	//---------------------------------------------------------------------
	// Implementation of BeanFactory interface
	//---------------------------------------------------------------------
	@Override
	public Object getBean(String name) throws BeansException {
		assertBeanFactoryActive();
		return getBeanFactory().getBean(name);
	}
	@Override
	public <T> T getBean(String name, Class<T> requiredType) throws BeansException {
		assertBeanFactoryActive();
		return getBeanFactory().getBean(name, requiredType);
	}
	@Override
	public Object getBean(String name, Object... args) throws BeansException {
		assertBeanFactoryActive();
		return getBeanFactory().getBean(name, args);
	}
	@Override
	public <T> T getBean(Class<T> requiredType) throws BeansException {
		assertBeanFactoryActive();
		return getBeanFactory().getBean(requiredType);
	}

getBeanFactory()方法是ConfigurableApplicationContext接口中的方法,AbstractApplicationContext通过此方法调用子类中的BeanFactory的getBean等方法,多说一句,其实IOC的单例bean,都在BeanFactory(DefaultListableBeanFactory)的父类DefaultSingletonBeanRegistry中的singletonObjects属性存放

 

 

 

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值