`

关于<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/>。酷

分享到:
评论

相关推荐

    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...

    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...

    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數據庫-...

    Spring AOP配置源码

    &lt;/beans&gt;&lt;context:annotation-config/&gt; &lt;context:component-scan base-package="com.spring.*"/&gt; 两行为开启spring的注解配置 &lt;aop:aspect id="aspect" ref="logIntercepter"&gt; 引入具体的AOP操作类 &lt;aop:pointcut ...

    SpringMVC-SSH全注解

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

    spring_MVC源码

    10. &lt;context:annotation-config /&gt; 11. &lt;!-- 把标记了@Controller注解的类转换为bean --&gt; 12. &lt;context:component-scan base-package="com.mvc.controller" /&gt; 13. &lt;!-- 启动Spring MVC的注解功能,...

    Spring Context测试

    学习spring组件扫描(Component Scanning)的代码 ...&lt;context:annotation-config /&gt; &lt;context:component-scan base-package="com.test"&gt;&lt;/context:component-scan&gt; 2.在需要装配的类的上面全部加上@Component

    轻量级高性能 RPC 框架 HRPC.zip

     &lt;context:annotation-config/&gt;  &lt;context:property-placeholder location="classpath:system.properties"/&gt;  &lt;!--客户端配置--&gt;  &lt;bean id="rpcClient" class="com.yingjun.rpc.client.RPCClient"&gt;  ...

    spring

    关于上下文:annotation-config与上下文:component-scan context:annotation-config:作用是可以使用@ Autowired,@ Inject等来省略xml配置文件中的属性属性,简化配置; context:component-scan:作用是可以...

    java微信公众号MVC开发框架

    spring配置文件中唯一需要配置的bean是WeixinConfigurer类,&lt;context:component-scan base-package="com.github.jweixin.jwx.weixin.service" /&gt;是可选配置,但里面封装了微信接口服务类,建议一定要配置进spring...

    客户关系管理系统框架搭建(二)

    &lt;context:component-scan base-package="cn.itcast.crm"/&gt; &lt;!--3 配置本地化代理工程bean,这是spring整合hibernate的入口 --&gt; &lt;bean id="sessionFactory" class="org.springframework.orm....

    springmybatis

    DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"&gt; &lt;configuration&gt; &lt;typeAliases&gt; &lt;typeAlias alias="User" type=...

    java8stream源码-java:java及相关(电话/微信:15850669069,qq:1056764180)

    context:annotation-config vscontext:component-scan linux部署运维 [Linux Tune Network Stack (Buffers Size) To Increase Networking Performance]) c++ 其他 [Real Time Analytics with Druid, Spark, and ...

Global site tag (gtag.js) - Google Analytics