最近做项目发现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/>。
相关推荐
<context:component-scan base-package="org.whvcse"></context:component-scan> <tx:annotation-driven transaction-manager="txManager" /> <!-- <aop:config> <aop:pointcut id="defaultServiceOperation" ...
<context:annotation-config/> <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"> <property name="driverClass" value="com.mysql.jdbc.Driver"></property> <property name="jdbc...
<context:annotation-config/> <!-- 扫描包 --> <context:component-scan base-package="com.org"/> <bean id="jspViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver...
<context:component-scan base-package="*" /> <!-- <aop:config>--> <!-- execution第一个星号代表任何返回类型,第二个星号代表com.sbz.service下的所有包,第三个星号代表所有方法,括号中的两个点代表任何...
<context:annotation-config/> <context:component-scan base-package="com.org.*" /> <bean id="jspViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property...
<context:annotation-config /> <context:component-scan base-package="com.mvc" /> <mvc:annotation-driven /> <mvc:resources mapping="/resources/**" location="/resources/" /> <mvc:default-servlet-...
<context:component-scan base-package="com.ccc"/> <bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping" p:order="0" /> <!-- 配置事务管理器 針對MES數據庫-...
</beans><context:annotation-config/> <context:component-scan base-package="com.spring.*"/> 两行为开启spring的注解配置 <aop:aspect id="aspect" ref="logIntercepter"> 引入具体的AOP操作类 <aop:pointcut ...
<context:annotation-config/> <!-- 扫描包 --> <context:component-scan base-package="com.org.core"/> <bean id="jspViewResolver" class="org.springframework.web.servlet.view....
10. <context:annotation-config /> 11. <!-- 把标记了@Controller注解的类转换为bean --> 12. <context:component-scan base-package="com.mvc.controller" /> 13. <!-- 启动Spring MVC的注解功能,...
学习spring组件扫描(Component Scanning)的代码 ...<context:annotation-config /> <context:component-scan base-package="com.test"></context:component-scan> 2.在需要装配的类的上面全部加上@Component
<context:annotation-config/> <context:property-placeholder location="classpath:system.properties"/> <!--客户端配置--> <bean id="rpcClient" class="com.yingjun.rpc.client.RPCClient"> ...
关于上下文:annotation-config与上下文:component-scan context:annotation-config:作用是可以使用@ Autowired,@ Inject等来省略xml配置文件中的属性属性,简化配置; context:component-scan:作用是可以...
spring配置文件中唯一需要配置的bean是WeixinConfigurer类,<context:component-scan base-package="com.github.jweixin.jwx.weixin.service" />是可选配置,但里面封装了微信接口服务类,建议一定要配置进spring...
<context:component-scan base-package="cn.itcast.crm"/> <!--3 配置本地化代理工程bean,这是spring整合hibernate的入口 --> <bean id="sessionFactory" class="org.springframework.orm....
DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration> <typeAliases> <typeAlias alias="User" type=...
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 ...