关于@PostConstruct不起作用,以及context:component-scan父子容器,事务失败

  • @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进行处理

 

你可能感兴趣的:(component)