- @PostConstruct关于这个没有生效,主要是@PostConstruct执行是在类实例化之后,如果bean归Spring管理,bean不能延迟加载(Spring xml 中default-lazy-init=false或在实体类上@Lazy(false))
- context:component-scan 是Spring 提供的扫描注解类,加载注解并实例化,如果MVC 采用的是Spring自己的, 就有存在父子容器的问题,bean的扫描重复覆盖,直至到时事务失效等等系列问题,context:component-scan 组件有一系列属性,主要如下
<context:component-scan base-package="" resource-pattern="**/*.class" name-generator="org.springframework.context.annotation.AnnotationBeanNameGenerator" use-default-filters="true" annotation-config="true"> <context:include-filter type="aspectj" expression=""/> <context:exclude-filter type="regex" expression=""/> </context:component-scan>
详情可以查询 http://www.iteye.com/topic/1121913 和 http://jinnianshilongnian.iteye.com/blog/1762632
文章中作者主要是修改了 base-package的路径,bean中扫描的和mvc中扫描的路径不一样,从而避免上述问题, 但这依赖于路径规划,
比如com.a.b.web com.a.b.servie
<context:component-scan base-package="com.a.b.web" use-default-filters="false">
<context:component-scan base-package="com.a.b.service" >
这里说下 use-default-filters , context:component-scan默认是为true的,标示扫描@Component、@ManagedBean、@Named , 默认帮你include-filter 这几个Annotion,include-filter和exclude-filter,会再如下进行过滤排除
protected boolean isCandidateComponent(MetadataReader metadataReader) throws IOException { for (TypeFilter tf : this.excludeFilters) { if (tf.match(metadataReader, this.metadataReaderFactory)) { return false; } } for (TypeFilter tf : this.includeFilters) { if (tf.match(metadataReader, this.metadataReaderFactory)) { AnnotationMetadata metadata = metadataReader.getAnnotationMetadata(); if (!metadata.isAnnotated(Profile.class.getName())) { return true; } AnnotationAttributes profile = MetadataUtils.attributesFor(metadata, Profile.class); return this.environment.acceptsProfiles(profile.getStringArray("value")); } } return false; }
如果项目路径相同(mvc和bean),则需要如下配置
MVC(Spring-mvc.xml):
<context:component-scan base-package="com.a.b" use-default-filters="false"> <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/> </context:component-scan>
Bean(application.xml)
<context:component-scan base-package="com.a.b"> <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/> </context:component-scan>
服务器启动application.xml先执行,此时use-default-filters=true是默认值会扫描(@Component、@ManagedBean、@Named),@Component是@Service、@Repository、@Controller的子集,但会被context:exclude-filter过滤到Controller,留下Service、Repository、Component
接着加载Spring-mvc.xml,此时use-default-filters=false,则是会检索到include-filter对应的Controller
正好mvc 和 application 分开加载注解。解决了重复加载的一些问题,如下
1、事务失效,以及Spring data jpa @Modifying注解异常
2、Spring的异步执行 @Async
总结:
主要是理解Spring context:component-scan的 注解和相关属性,会交给ContextNamespaceHandler类,具体是ComponentScanBeanDefinitionParser类读取,并有ClassPathBeanDefinitionScanner进行处理