spring源码一

spring在beanFactory的基础上提供了一些具体容器实现

1、AnnotationConfigApplicationContext:是一个用来管理注解bean容器的

2、ClassPathXmlApplicationContext:主要用在在类路径加载xml文件的场景

 

今天主要介绍AnnotationConfigApplicationContext

  • AnnotationConfigApplicationContext继承了GenericApplicationContext这个通用应用上下文,GenericApplicationContext内部定义了一个DefaultListableBeanFactory实例,GenericApplicationContext实现了BeanDefinitionRegistry接口,所以可以通过AnnotationConfigApplicationContext实例注册beanDefinition,然后通过调用refresh()方法来初始化上下文
    • AnnotationConfigApplicationContext继承了AbstractApplicationContext,AbstractApplicationContext提供了ApplicationContext的抽象实现

1、下面通过实例演示AnnotationConfigApplicationContext的初始化过程

AnnotationConfigApplicationContext annotationConfigApplicationContext =
				new AnnotationConfigApplicationContext(AppConfig.class);

2、AnnotationConfigApplicationContext的构造方法

/**
	 * 这个构造方法需要传入一个被javaConfig(@Configuration)注解了的配置类
	 * 然后会把这个被@Configuration注解了的类通过注解读取器读取后继而解析
	 * Create a new AnnotationConfigApplicationContext, deriving bean definitions
	 * from the given annotated classes and automatically refreshing the context.
	 * @param annotatedClasses one or more annotated classes,
	 * e.g. {@link Configuration @Configuration} classes
	 */
	public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {
		// 这里由于他有父类,故而会先调用父类的构造方法,然后才会调用自己的构造方法
		// 在自己的构造方法中初始一个读取器和扫描器
		this();// 这里会初始化读取器和扫描器,看下面
		register(annotatedClasses);
		refresh();
	}


/**
	 * 初始化一个bean的读取器和扫描器
	 *
	 * 默认构造函数,如果直接调用这个默认的构造方法,需要在稍后通过调用register()
	 * 去注册配置类(加了@Configuration注解的类),并调用refresh()方法刷新容器
	 * 触发器对注解Bean的载入,解析和注册过程
	 * Create a new AnnotationConfigApplicationContext that needs to be populated
	 * through {@link #register} calls and then manually {@linkplain #refresh refreshed}.
	 */
	public AnnotationConfigApplicationContext() {
		/**
		 * AnnotatedBeanDefinition:	加了注解类的描述
		 * 创建一个读取注解的Bean定义读取器
		 * 什么事Bean定义? BeanDefinition
		 *
		 * 在IOC容器中初始化一个 注解bean读取器AnnotatedBeanDefinitionReader
		 */
		this.reader = new AnnotatedBeanDefinitionReader(this);

		// 在IOC容器中初始化一个 按类路径扫描注解bean的 扫描器
		this.scanner = new ClassPathBeanDefinitionScanner(this);
	}

3、GenericApplicationContext部分代码:

/**
	 * 实例化一个工厂
	 * Create a new GenericApplicationContext.
	 * @see #registerBeanDefinition
	 * @see #refresh
	 */
	public GenericApplicationContext() {
		this.beanFactory = new DefaultListableBeanFactory();
	}

4、AnnotationConfigApplicationContext的register(annotatedClasses)是注册bean配置类,实现bean的读取,方法如下走

/**
	 * 这个构造方法需要传入一个被javaConfig(@Configuration)注解了的配置类
	 * 然后会把这个被@Configuration注解了的类通过注解读取器读取后继而解析
	 * Create a new AnnotationConfigApplicationContext, deriving bean definitions
	 * from the given annotated classes and automatically refreshing the context.
	 * @param annotatedClasses one or more annotated classes,
	 * e.g. {@link Configuration @Configuration} classes
	 */
	public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {
		// 这里由于他有父类,故而会先调用父类的构造方法,然后才会调用自己的构造方法
		// 在自己的构造方法中初始一个读取器和扫描器
		this();
        /**
		 * register方法重点完成了bean配置类本身的解析和注册,处理过程可以分为以下几个步骤:
		 * 	 1.根据bean配置类,使用BeanDefinition解析Bean的定义信息,主要是一些注解信息
		 * 	 2.Bean作用域的处理,默认缺少@Scope注解,解析成单例
		 * 	 3.借助AnnotationConfigUtils工具类解析通用注解
		 * 	 4.将bean定义信息已beanname,beandifine键值对的形式注册到ioc容器中
		 */
		register(annotatedClasses);
		refresh();
	}


/**
	 * 注册单个bean给容器
	 * 比如有新的bean可以用这个方法
	 * 但是注册之后需要手动调用refresh()方法去出发容器解析注解
	 *
	 * 有2个意思
	 * 1、可以注册一个配置类
	 * 2、可以单独注册一个bean
	 * Register one or more annotated classes to be processed.
	 * <p>Note that {@link #refresh()} must be called in order for the context
	 * to fully process the new classes.
	 * @param annotatedClasses one or more annotated classes,
	 * e.g. {@link Configuration @Configuration} classes
	 * @see #scan(String...)
	 * @see #refresh()
	 */
	@Override
	public void register(Class<?>... annotatedClasses) {
		Assert.notEmpty(annotatedClasses, "At least one annotated class must be specified");
		this.reader.register(annotatedClasses);
	}


/**
	 * Register one or more annotated classes to be processed.
	 * <p>Calls to {@code register} are idempotent; adding the same
	 * annotated class more than once has no additional effect.
	 * @param annotatedClasses one or more annotated classes,
	 * e.g. {@link Configuration @Configuration} classes
	 */
	public void register(Class<?>... annotatedClasses) {
		for (Class<?> annotatedClass : annotatedClasses) {
			registerBean(annotatedClass);
		}
	}



/**
	 * Register a bean from the given bean class, deriving its metadata from
	 * class-declared annotations.
	 * @param annotatedClass the class of the bean
	 */
	public void registerBean(Class<?> annotatedClass) {
		doRegisterBean(annotatedClass, null, null, null);
	}



// 方法的最终实现是在AnnotatedBeanDefinitionReader类中
/**
	 * register方法重点完成了bean配置类本身的解析和注册,处理过程可以分为以下几个步骤:
	 * 		1.根据bean配置类,使用BeanDefinition解析Bean的定义信息,主要是一些注解信息
	 * 		2.Bean作用域的处理,默认缺少@Scope注解,解析成单例
	 * 		3.借助AnnotationConfigUtils工具类解析通用注解
	 * 		将bean定义信息已beanname,beandifine键值对的形式注册到ioc容器中
	 * 	
	 * 	
	 * Register a bean from the given bean class, deriving its metadata from
	 * class-declared annotations.
	 * @param annotatedClass the class of the bean
	 * @param instanceSupplier a callback for creating an instance of the bean
	 * (may be {@code null})
	 * @param name an explicit name for the bean
	 * @param qualifiers specific qualifier annotations to consider, if any,
	 * in addition to qualifiers at the bean class level
	 * @param definitionCustomizers one or more callbacks for customizing the
	 * factory's {@link BeanDefinition}, e.g. setting a lazy-init or primary flag
	 * @since 5.0
	 */
	<T> void doRegisterBean(Class<T> annotatedClass, @Nullable Supplier<T> instanceSupplier, @Nullable String name,
							@Nullable Class<? extends Annotation>[] qualifiers, BeanDefinitionCustomizer... definitionCustomizers) {

		/**
		 * 根据指定的bean创建一个AnnotatedGenericBeanDefinition
		 * 这个AnnotatedGenericBeanDefinition可以理解为一个数据结构
		 * AnnotatedGenericBeanDefinition主要是用来描述类的注解信息,比如一些元信息
		 * 如Scope,Lazy,Primary,DependsOn,Role,Description等
		 *
		 */
		AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(annotatedClass);

		/**
		 * 判断这个类是否需要跳过解析
		 * 通过代码可以知道spring判断是否跳过解析,主要判断类有没有加注解
		 */
		if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
			return;
		}

		/**
		 * 设置回调
		 */
		abd.setInstanceSupplier(instanceSupplier);

		/**
		 * 解析bean作用域(单例或者原型),如果有@Scope注解,则解析@Scope,没有则默认为singleton
		 */
		ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);

		/**
		 * 把类的作用域添加到AnnotatedGenericBeanDefinition(数据结构中)
		 */
		abd.setScope(scopeMetadata.getScopeName());
		/**
		 * 生成bean配置类beanName
		 */
		String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));

		/**
		 * 处理类当中的通用注解
		 * 分析源码可以知道他主要处理
		 * Lazy, primary DependsOn, Role ,Description这五个注解
		 * 处理完成之后processCommonDefinitionAnnotations中依然是把他添加到数据结构当中
		 */
		AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);

		/**
		 * 如果在向容器注册注解Bean定义时,使用了额外的限定符注解则解析
		 * @Qualifier:注入指定名称的bean;
		 * @Primary:自动装配时当出现多个Bean候选者时,被注解为@Primary的Bean将作为首选者,否则将抛出异常
		 * 这里需要注意的是
		 * byName和@Qualifier这个变量是Annotaion类型数组,里面存的不仅仅是@Qualifier注解
		 * 理论上里面存的是一切注解,所以可以看到下面的代码spring去循环这个数组
		 * 然后依次判断了注解当中是否包含了Primary,是否包含了Lazy
		 */
		if (qualifiers != null) {
			for (Class<? extends Annotation> qualifier : qualifiers) {
				// 如果配置了@Primary注解,如果加了则作为首选
				if (Primary.class == qualifier) {
					// 如果配置@Primary注解,则设置当前Bean为自动装配autowire时首选bean
					abd.setPrimary(true);
				}
				else if (Lazy.class == qualifier) {
					//设置当前bean为延迟加载
					abd.setLazyInit(true);
				}
				else {
					// 如果使用了除@Primary和@Lazy以外的其他注解,则为该Bean添加一个根据名字自动装配的限定符
					abd.addQualifier(new AutowireCandidateQualifier(qualifier));
				}
			}
		}
		/**
		 * 自定义bean注册,通常用在applicationContext创建后,手动向容器中一lambda表达式的方式注册bean,
		 * 比如:applicationContext.registerBean(UserService.class, () -> new UserService());
		 */
		for (BeanDefinitionCustomizer customizer : definitionCustomizers) {
			//自定义bean添加到BeanDefinition
			customizer.customize(abd);
		}

		/**
		 * 这个BeanDefinitionHolder也是一个数据结构(底层是个数据)
		 * key是存放了这个bean的所有元信息
		 * value存放的是这个bean的beanName
		 */
		BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
		//创建代理对象
		definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);

		/**
		 * 把上述的这个数据结构注册给registry
		 * registry就是AnnotationConfigApplicationContext
		 * AnnotationConfigApplicationContext在初始化的时候通过调用父类的构造方法
		 * 实例化一个DefaultListableBeanFactory
		 * registerBeanDefinition里面就是把definitionHolder这个数据结构包含的信息注册到
		 * DefaultListableBeanFactory这个工厂
		 */
		BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
	}

register方法重点完成了bean配置类本身的解析和注册,处理过程可以分为以下几个步骤:

  1. 根据bean配置类,使用BeanDefinition解析Bean的定义信息,主要是一些注解信息
  2. Bean作用域的处理,默认缺少@Scope注解,解析成单例
  3. 借助AnnotationConfigUtils工具类解析通用注解
  4. 将bean定义信息已beanname,beandifine键值对的形式注册到ioc容器中

5、refresh()刷新上下文

 refresh方法在AbstractApplicationContext容器中实现,refresh()方法的作用加载或者刷新当前的配置信息,如果已经存在spring容器,则先销毁之前的容器,重新创建spring容器,载入bean定义,完成容器初始化工作,所以可以看出AnnotationConfigApplicationContext容器是通过调用其父类AbstractApplicationContext的refresh()函数启动整个IoC容器完成对Bean定义的载入。     

// refresh()方法的最终实现是在AbstractApplicationContext类中
public void refresh() throws BeansException, IllegalStateException {
		synchronized (this.startupShutdownMonitor) {
			// Prepare this context for refreshing.
			// 准备工作包括设置启动时间,是否激活标识位,初始化属性源(propert source)配置
			//1.刷新前的预处理
			prepareRefresh();

			// Tell the subclass to refresh the internal bean factory.
			//2.获取刷新后的内部Bean工厂
			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

			// Prepare the bean factory for use in this context.
			//3.BeanFactory的预准备工作
			prepareBeanFactory(beanFactory);

			try {
				// Allows post-processing of the bean factory in context subclasses.
				// BeanFactory准备工作完成后,可以做一些后置处理工作,
				// 4.空方法,用于在容器的子类中扩展
				postProcessBeanFactory(beanFactory);

				// Invoke factory processors registered as beans in the context.
				// 5. 执行BeanFactoryPostProcessor的方法,BeanFactory的后置处理器,
				// 在BeanFactory标准初始化之后执行的
				invokeBeanFactoryPostProcessors(beanFactory);

				// Register bean processors that intercept bean creation.
				// 6. 注册BeanPostProcessor(Bean的后置处理器),用于拦截bean创建过程
				registerBeanPostProcessors(beanFactory);

				// Initialize message source for this context.
				// 7. 初始化MessageSource组件(做国际化功能;消息绑定,消息解析)
				initMessageSource();

				// Initialize event multicaster for this context.
				// 8. 初始化事件派发器
				initApplicationEventMulticaster();

				// Initialize other special beans in specific context subclasses.
				// 9.空方法,可以用于子类实现在容器刷新时自定义逻辑
				onRefresh();

				// Check for listener beans and register them.
				// 10. 注册时间监听器,将所有项目里面的ApplicationListener注册到容器中来
				registerListeners();

				// Instantiate all remaining (non-lazy-init) singletons.
				// 11. 初始化所有剩下的单实例bean,单例bean在初始化容器时创建,
				// 原型bean在获取时(getbean)时创建
				finishBeanFactoryInitialization(beanFactory);

				// Last step: publish corresponding event.
				// 12. 完成BeanFactory的初始化创建工作,IOC容器就创建完成;
				finishRefresh();
			}

			catch (BeansException ex) {
				if (logger.isWarnEnabled()) {
					logger.warn("Exception encountered during context initialization - " +
							"cancelling refresh attempt: " + ex);
				}

				// Destroy already created singletons to avoid dangling resources.
				destroyBeans();

				// Reset 'active' flag.
				cancelRefresh(ex);

				// Propagate exception to caller.
				throw ex;
			}

			finally {
				// Reset common introspection caches in Spring's core, since we
				// might not ever need metadata for singleton beans anymore...
				resetCommonCaches();
			}
		}
	}

// 重点分析
//1.刷新前的预处理
prepareRefresh();

/**
	 * Prepare this context for refreshing, setting its startup date and
	 * active flag as well as performing any initialization of property sources.
	 */
	protected void prepareRefresh() {
		// Switch to active.
		//设置容器启动时间
		this.startupDate = System.currentTimeMillis();
		//启动标识
		this.closed.set(false);
		this.active.set(true);

		if (logger.isDebugEnabled()) {
			if (logger.isTraceEnabled()) {
				logger.trace("Refreshing " + this);
			}
			else {
				logger.debug("Refreshing " + getDisplayName());
			}
		}

		// Initialize any placeholder property sources in the context environment.
		// 这个方法目前没有子类实现
		// 估计spring是期待后面版本有子类实现吧
		initPropertySources();

		// Validate that all properties marked as required are resolvable:
		// see ConfigurablePropertyResolver#setRequiredProperties
		//检验属性的合法等
		getEnvironment().validateRequiredProperties();

		// Store pre-refresh ApplicationListeners...
		if (this.earlyApplicationListeners == null) {
			this.earlyApplicationListeners = new LinkedHashSet<>(this.applicationListeners);
		}
		else {
			// Reset local application listeners to pre-refresh state.
			this.applicationListeners.clear();
			this.applicationListeners.addAll(this.earlyApplicationListeners);
		}

		// Allow for the collection of early ApplicationEvents,
		// to be published once the multicaster is available...
		//保存容器中的一些早期的事件
		this.earlyApplicationEvents = new LinkedHashSet<>();
	}


// 第2步中
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
		//为beanfactory生成唯一序列化id,beanfactory已经在GenericApplicationContext构造函数中初始化了,
		// refreshBeanFactory的逻辑在AbstractApplicationContext的实现类GenericApplicationContext中
		refreshBeanFactory();
		//获取beanfactory
		return getBeanFactory();
	}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值