spring 加载应用上下文方式:


一、 从Web应用下的一个或多个XML配置文件中加载应用上下文

此上下文在 DispatchServlet 创建上下文时使用, 通过xml 启动时创建web上下文.

ApplicationContext ac1 = new XmlWebApplicationContext();

FrameworkServlet.java

	/**
	 * xml启动的 web应用上下文
	 */
	public static final Class<?> DEFAULT_CONTEXT_CLASS = XmlWebApplicationContext.class;
	/**
	 * 默认 XmlWebApplicationContext.class
	 */
	private Class<?> contextClass = DEFAULT_CONTEXT_CLASS;

	public Class<?> getContextClass() {
		return this.contextClass;
	}

	/**
	 * 创建web应用上下文,创建 XmlWebApplicationContext.class
	 */
	protected WebApplicationContext createWebApplicationContext(@Nullable ApplicationContext parent) {
		Class<?> contextClass = getContextClass();
		if (!ConfigurableWebApplicationContext.class.isAssignableFrom(contextClass)) {
			throw new ApplicationContextException("error");
		}
		ConfigurableWebApplicationContext wac = (ConfigurableWebApplicationContext) BeanUtils.instantiateClass(contextClass);

		wac.setEnvironment(getEnvironment());
		wac.setParent(parent);
		String configLocation = getContextConfigLocation();
		if (configLocation != null) {
			wac.setConfigLocation(configLocation);
		}
		//配置与刷新web应用上下文
		configureAndRefreshWebApplicationContext(wac);

		return wac;
	}
二、 从类路径下的一个或多个XML配置文件中加载上下文定义,把应用上下文的定义文件作为类资源

通过主动配置 xml 资源路径, 创建应用上下文.

ApplicationContext ac2 = new ClassPathXmlApplicationContext();

ClassPathXmlApplicationContext


	// demo
	ApplicationContext context = new ClassPathXmlApplicationContext("/org/springframework/web/context/WEB-INF/applicationContext.xml");
	
	public ClassPathXmlApplicationContext(
			String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)
			throws BeansException {

		super(parent);
		setConfigLocations(configLocations);
		if (refresh) {
			refresh();  // 在第二步:解析资源路径
		}
	}

三、 从文件系统下的一个或多个XML配置中加载上下文定义

ClassPathXmlApplicationContext 相似, 在于 FileSystemXmlApplicationContext 初始化时, 可以直接url转换 FileSystemResource 对象.

ApplicationContext ac3 = new FileSystemXmlApplicationContext();

	protected Resource getResourceByPath(String path) {
		if (path.startsWith("/")) {
			path = path.substring(1);
		}
		return new FileSystemResource(path);
	}
四、 从一个或多个基于Java的配置类中加载 应用上下文

注解配置上下文, 可通过注册 @Configurable 注解配置的类来创建上下文,或者可通过配置扫描 package 路径来创建上下文.

ApplicationContext ac4 = new AnnotationConfigApplicationContext();

AnnotationConfigApplicationContext

	// 注解读取器
	private final AnnotatedBeanDefinitionReader reader;
	// 路径扫描器
	private final ClassPathBeanDefinitionScanner scanner;
	
	/**
	 * 注册单个或者多个Bean
	 */
	public void register(Class<?>... annotatedClasses) {
		Assert.notEmpty(annotatedClasses, "At least one annotated class must be specified");
		this.reader.register(annotatedClasses);
	}

	/**
	 * 扫描给定的路径
	 */
	public void scan(String... basePackages) {
		Assert.notEmpty(basePackages, "At least one base package must be specified");
		this.scanner.scan(basePackages);
	}
五、 从一个或多个基于Java的配置类中加载 Web应用上下文

注解配置web应用上下文, 可通过注册 @Configurable 注解配置的类来创建web上下文,或者可通过配置扫描 package 路径来创建web上下文. 重写 loadBeanDefinitions(DefaultListableBeanFactory beanFactory) 方法. 实现加载操作。

ApplicationContext ac5 = new AnnotationConfigWebApplicationContext();

	/**
	 * 注册一个或多个要处理的带注释的类
	 */
	public void register(Class<?>... annotatedClasses) {
		Assert.notEmpty(annotatedClasses, "At least one annotated class must be specified");
		Collections.addAll(this.annotatedClasses, annotatedClasses);
	}

	/**
	 * 在指定的基本包中执行扫描
	 */
	public void scan(String... basePackages) {
		Assert.notEmpty(basePackages, "At least one base package must be specified");
		Collections.addAll(this.basePackages, basePackages);
	}

	/**
	 * 注册一个{@link org.springframework.beans.factory.config.BeanDefinition}为{@link #register(Class[])}指定的任何类,
	 * 扫描{@link #scan(String...)}指定的任何包
	 */
	@Override
	protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) {
		AnnotatedBeanDefinitionReader reader = getAnnotatedBeanDefinitionReader(beanFactory);
		ClassPathBeanDefinitionScanner scanner = getClassPathBeanDefinitionScanner(beanFactory);

		BeanNameGenerator beanNameGenerator = getBeanNameGenerator();
		if (beanNameGenerator != null) {
			reader.setBeanNameGenerator(beanNameGenerator);
			scanner.setBeanNameGenerator(beanNameGenerator);
			beanFactory.registerSingleton(AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR, beanNameGenerator);
		}

		ScopeMetadataResolver scopeMetadataResolver = getScopeMetadataResolver();
		if (scopeMetadataResolver != null) {
			reader.setScopeMetadataResolver(scopeMetadataResolver);
			scanner.setScopeMetadataResolver(scopeMetadataResolver);
		}

		if (!this.annotatedClasses.isEmpty()) {
			if (logger.isDebugEnabled()) {
				logger.debug("Registering annotated classes: [" +
						StringUtils.collectionToCommaDelimitedString(this.annotatedClasses) + "]");
			}
			reader.register(ClassUtils.toClassArray(this.annotatedClasses));
		}

		if (!this.basePackages.isEmpty()) {
			if (logger.isDebugEnabled()) {
				logger.debug("Scanning base packages: [" +
						StringUtils.collectionToCommaDelimitedString(this.basePackages) + "]");
			}
			scanner.scan(StringUtils.toStringArray(this.basePackages));
		}

		String[] configLocations = getConfigLocations();
		if (configLocations != null) {
			for (String configLocation : configLocations) {
				try {
					Class<?> clazz = ClassUtils.forName(configLocation, getClassLoader());
					if (logger.isTraceEnabled()) {
						logger.trace("Registering [" + configLocation + "]");
					}
					reader.register(clazz);
				}
				catch (ClassNotFoundException ex) {
					if (logger.isTraceEnabled()) {
						logger.trace("Could not load class for config location [" + configLocation +
								"] - trying package scan. " + ex);
					}
					int count = scanner.scan(configLocation);
					if (count == 0 && logger.isDebugEnabled()) {
						logger.debug("No annotated classes found for specified class/package [" + configLocation + "]");
					}
				}
			}
		}
	}

版权声明:本文为baidu_36327010原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/baidu_36327010/article/details/103229516