`

关于<context:component-scan/>与<context:annotation-config>问题

阅读更多

   最近做项目发现Spring核心配置文件中的<context:component-scan/>与<context:annotation-config/>配置经常一起出现,但有时候又单独出现,而且没有出现问题。今天抽空看了看源码,发现原来这俩个标签的处理逻辑及其相似(在处理我们经常使用的几个注解上基本如出一辙)。

   起初,添加<context:annotation-config/>标签,想必是为了我们大家使用像@Autowired、@Resource、@PostConstruct、@PreDestroy等等标签方便,以为之前我们注册BeanPostProcessor都是直接在Spring配置文件中使用<bean/>标签声明的方式,如果使用的注解一旦多起来,像我这样的懒人实在是难以接受。像我们常用的几个:

@Autowired

<bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor "/>

 @Resource/@PostConstruct/@PreDestroy

<bean class="org.springframework.context.annotation.CommonAnnotationBeanPostProcessor"/>

 @Required

<bean class="org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor"/>

 @PersistenceContext

<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor"/>

 

而<context:annotation-config/>的出现解放了我们的体力,只需一行配置就搞定了。

上源码:

<context:annotation-config/>由AnnotationConfigBeanDefinitionParser解析:

public class AnnotationConfigBeanDefinitionParser implements BeanDefinitionParser {

	public BeanDefinition parse(Element element, ParserContext parserContext) {
		Object source = parserContext.extractSource(element);

		// Obtain bean definitions for all relevant BeanPostProcessors.
		Set<BeanDefinitionHolder> processorDefinitions =
				AnnotationConfigUtils.registerAnnotationConfigProcessors(parserContext.getRegistry(), source);//此处为BeanPostProcessor 注册部分

		// Register component for the surrounding <context:annotation-config> element.
		CompositeComponentDefinition compDefinition = new CompositeComponentDefinition(element.getTagName(), source);
		parserContext.pushContainingComponent(compDefinition);

		// Nest the concrete beans in the surrounding component.
		for (BeanDefinitionHolder processorDefinition : processorDefinitions) {
			parserContext.registerComponent(new BeanComponentDefinition(processorDefinition));
		}

		// Finally register the composite component.
		parserContext.popAndRegisterContainingComponent();

		return null;
	}

}

 AnnotationConfigUtils.registerAnnotationConfigProcessor(..)

public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(
			BeanDefinitionRegistry registry, Object source) {

		Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<BeanDefinitionHolder>(4);

		if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
			RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
			def.setSource(source);
			beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
		}

		if (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
                        //@Autowired等
			RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);
			def.setSource(source);
			beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
		}

		if (!registry.containsBeanDefinition(REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {                   //@Required等
			RootBeanDefinition def = new RootBeanDefinition(RequiredAnnotationBeanPostProcessor.class);
			def.setSource(source);
			beanDefs.add(registerPostProcessor(registry, def, REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
		}

		// Check for JSR-250 support, and if present add the CommonAnnotationBeanPostProcessor.
		if (jsr250Present && !registry.containsBeanDefinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)) {    //@PostConstruct、@PreDestroy、@Resource等
			RootBeanDefinition def = new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class);
			def.setSource(source);
			beanDefs.add(registerPostProcessor(registry, def, COMMON_ANNOTATION_PROCESSOR_BEAN_NAME));
		}

		// Check for JPA support, and if present add the PersistenceAnnotationBeanPostProcessor.
		if (jpaPresent && !registry.containsBeanDefinition(PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME)) {  //@PersistenceContext
			RootBeanDefinition def = new RootBeanDefinition();
			try {
				ClassLoader cl = AnnotationConfigUtils.class.getClassLoader();
				def.setBeanClass(cl.loadClass(PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME));
			}
			catch (ClassNotFoundException ex) {
				throw new IllegalStateException(
						"Cannot load optional framework class: " + PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME, ex);
			}
			def.setSource(source);
			beanDefs.add(registerPostProcessor(registry, def, PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME));
		}

		return beanDefs;
	}

 

 以上我们可以清晰的看到标签<context:annotation-config/>的解析过程以及注解相关的BeanPostProcessor的注册过程。接下来我们来看看<context:component-scan/>的逻辑:

ComponentScanBeanDefinitionParser

public class ComponentScanBeanDefinitionParser implements BeanDefinitionParser {

public BeanDefinition parse(Element element, ParserContext parserContext) {
		String[] basePackages = StringUtils.tokenizeToStringArray(element.getAttribute(BASE_PACKAGE_ATTRIBUTE),
				ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS);

		// Actually scan for bean definitions and register them.
		ClassPathBeanDefinitionScanner scanner = configureScanner(parserContext, element);         //扫描指定路径下的类,并注册BeanPostProcessor
		Set<BeanDefinitionHolder> beanDefinitions = scanner.doScan(basePackages);
		registerComponents(parserContext.getReaderContext(), beanDefinitions, element);

		return null;
	}




}

 

 

protected void registerComponents(
			XmlReaderContext readerContext, Set<BeanDefinitionHolder> beanDefinitions, Element element) {
	 ... ...
		// Register annotation config processors, if necessary.
		boolean annotationConfig = true;
		if (element.hasAttribute(ANNOTATION_CONFIG_ATTRIBUTE)) {
			annotationConfig = Boolean.valueOf(element.getAttribute(ANNOTATION_CONFIG_ATTRIBUTE));
		}
		if (annotationConfig) {
			Set<BeanDefinitionHolder> processorDefinitions =
					AnnotationConfigUtils.registerAnnotationConfigProcessors(readerContext.getRegistry(), source);
			for (BeanDefinitionHolder processorDefinition : processorDefinitions) {
				compositeDef.addNestedComponent(new BeanComponentDefinition(processorDefinition));
			}
		}
		... ...
	}

     我们可以发现Spring默认<context:component-scan/>的annotation-config的属性值为true,当其为true时,才对一些BeanPostProcessor进行注册,也就是完成<context:annotation-config/>的任务。

  从以上源码我们可以看出如果我们在使用<context:component-scan/>时不将其annotation-config属性设置为false的话,我们就可以不配置<context:annotation-config/>。酷

分享到:
评论

相关推荐

    Spring注解详解

    &lt;context:annotation-config /&gt; ``` 这将隐式地向 Spring 容器注册 `AutowiredAnnotationBeanPostProcessor`、`CommonAnnotationBeanPostProcessor`、`PersistenceAnnotationBeanPostProcessor` 和 `...

    集成springmvc spring hibernate的配置

    &lt;context:annotation-config /&gt; &lt;context:component-scan base-package="com.mvc.*"&gt; &lt;context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller" /&gt; &lt;/context:component...

    struts2.3+hibernate3.6+spring3.1整合的纯xml配置的小项目

    &lt;context:component-scan base-package="org.whvcse"&gt;&lt;/context:component-scan&gt; &lt;tx:annotation-driven transaction-manager="txManager" /&gt; &lt;!-- &lt;aop:config&gt; &lt;aop:pointcut id="defaultServiceOperation" ...

    维生药业小项目 SSH简单学习项目

    &lt;context:annotation-config/&gt; &lt;bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"&gt; &lt;property name="driverClass" value="com.mysql.jdbc.Driver"&gt;&lt;/property&gt; &lt;property name="jdbc...

    使用Spring2.5的Autowired实现注释型的IOC

    在上面的配置文件中,我们使用了 `&lt;context:annotation-config/&gt;` 和 `&lt;context:component-scan base-package="testspring.main"/&gt;` 两个标签。 `&lt;context:annotation-config/&gt;` 用于启用注释型的 IOC,而 `&lt;context...

    springmvc-ibatis

    &lt;context:annotation-config/&gt; &lt;!-- 扫描包 --&gt; &lt;context:component-scan base-package="com.org"/&gt; &lt;bean id="jspViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver...

    spring3.2+strut2+hibernate4

    &lt;context:component-scan base-package="*" /&gt; &lt;!-- &lt;aop:config&gt;--&gt; &lt;!-- execution第一个星号代表任何返回类型,第二个星号代表com.sbz.service下的所有包,第三个星号代表所有方法,括号中的两个点代表任何...

    SpringMVC+Hibernate全注解整合

    &lt;context:annotation-config/&gt; &lt;context:component-scan base-package="com.org.*" /&gt; &lt;bean id="jspViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"&gt; &lt;property...

    15、spring 配置以及使用 1

    在这个主题中,我们将深入探讨`&lt;context:annotation-config&gt;`与`&lt;context:component-scan&gt;`的区别,事务管理器的配置,以及Spring开发环境的选择和数据源的配置。 1. `&lt;context:annotation-config&gt;`和`&lt;context:...

    SSM三大框架的整合.docx

    &lt;bean id="logbackConfigLocation" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean"&gt; &lt;property name="targetObject" value="java.lang.System" /&gt; &lt;property name="targetMethod" ...

    Spring3中配置DBCP,C3P0,Proxool,Bonecp数据源

    &lt;context:annotation-config /&gt; &lt;context:component-scan base-package="com.mvc" /&gt; &lt;mvc:annotation-driven /&gt; &lt;mvc:resources mapping="/resources/**" location="/resources/" /&gt; &lt;mvc:default-servlet-...

    spring applicationContext 配置文件

    &lt;context:component-scan base-package="com.ccc"/&gt; &lt;bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping" p:order="0" /&gt; &lt;!-- 配置事务管理器 針對MES數據庫-...

    简单SpringMVC环境搭建项目代码

    &lt;context:component-scan base-package="com.yourpackage" /&gt; &lt;mvc:annotation-driven/&gt; &lt;bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"&gt; &lt;property name="prefix" ...

    SSH整合配置.doc

    &lt;context:component-scan base-package="com.example"/&gt; &lt;bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"&gt; &lt;property name="dataSource" ref="dataSource"/&gt; ...

    SpringMVC环境搭建

    &lt;context:component-scan base-package="com.springmvc.learn" /&gt; &lt;mvc:annotation-driven/&gt; &lt;bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"&gt; &lt;property name="prefix" ...

    自己写网页spring框架搭建

    - 使用`&lt;context:annotation-config/&gt;`来启用Spring MVC的注解支持。 - **控制器扫描**: - 通过`&lt;context:component-scan base-package="controller"/&gt;`指定要扫描的控制器包名。 - **视图解析器**: - 配置视图...

Global site tag (gtag.js) - Google Analytics