在引入Spring的Validated时,需要声明如下bean:
 
@Bean
public MethodValidationPostProcessor methodValidationPostProcessor() {
return new MethodValidationPostProcessor();
}
出于偷懒,放在了如下的一个初始化中:
@Configuration
public class ConfigService implements WebMvcConfigurer { ......... @Bean
public MethodValidationPostProcessor methodValidationPostProcessor() {
return new MethodValidationPostProcessor();
} ......... }
配置好后,@Validated生效了,但是aop,事务等出现异常。启动日志如下:
2018-08-25 20:03:09 [INFO] [main] [o.s.c.s.PostProcessorRegistrationDelegate$BeanPostProcessorChecker][328] Bean 'org.springframework.boot.context.properties.ConversionServiceDeducer$Factory' of type [org.springframework.boot.context.properties.ConversionServiceDeducer$Factory] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2018-08-25 20:03:09 [INFO] [main] [o.s.c.s.PostProcessorRegistrationDelegate$BeanPostProcessorChecker][328] Bean 'mybatis-org.mybatis.spring.boot.autoconfigure.MybatisProperties' of type [org.mybatis.spring.boot.autoconfigure.MybatisProperties] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2018-08-25 20:03:09 [INFO] [main] [o.s.c.s.PostProcessorRegistrationDelegate$BeanPostProcessorChecker][328] Bean 'org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration' of type [org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration$$EnhancerBySpringCGLIB$$f57f05de] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2018-08-25 20:03:09 [INFO] [main] [o.s.c.s.PostProcessorRegistrationDelegate$BeanPostProcessorChecker][328] Bean 'org.springframework.boot.autoconfigure.jdbc.DataSourceConfiguration$Hikari' of type [org.springframework.boot.autoconfigure.jdbc.DataSourceConfiguration$Hikari] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2018-08-25 20:03:09 [INFO] [main] [o.s.c.s.PostProcessorRegistrationDelegate$BeanPostProcessorChecker][328] Bean 'spring.datasource-org.springframework.boot.autoconfigure.jdbc.DataSourceProperties' of type [org.springframework.boot.autoconfigure.jdbc.DataSourceProperties] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2018-08-25 20:03:09 [INFO] [main] [o.s.c.s.PostProcessorRegistrationDelegate$BeanPostProcessorChecker][328] Bean 'dataSource' of type [com.zaxxer.hikari.HikariDataSource] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2018-08-25 20:03:10 [INFO] [main] [o.s.c.s.PostProcessorRegistrationDelegate$BeanPostProcessorChecker][328] Bean 'sqlSessionFactory' of type [org.apache.ibatis.session.defaults.DefaultSqlSessionFactory] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2018-08-25 20:03:10 [INFO] [main] [o.s.c.s.PostProcessorRegistrationDelegate$BeanPostProcessorChecker][328] Bean 'sqlSessionTemplate' of type [org.mybatis.spring.SqlSessionTemplate] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
从日志提示的地方看到如下代码:
        @Override
public Object postProcessAfterInitialization(Object bean, String beanName) {
if (!(bean instanceof BeanPostProcessor) && !isInfrastructureBean(beanName) &&
this.beanFactory.getBeanPostProcessorCount() < this.beanPostProcessorTargetCount) {
if (logger.isInfoEnabled()) {
logger.info("Bean '" + beanName + "' of type [" + bean.getClass().getName() +
"] is not eligible for getting processed by all BeanPostProcessors " +
"(for example: not eligible for auto-proxying)");
}
}
return bean;
}
因为问题的引入是已知的,所以,在这里打了断点测试了下进入的条件。发现在加上MethodValidationPostProcessor的bean时,this.beanFactory.getBeanPostProcessorCount()获取到的值为10,不加这个bean时,获取到的值为21.那有问题,肯定是构造完成后,处理流程差异导致的问题。从构造函数开始寻找BeanPostProcessorChecker的初始化地点。
从这里找到PostProcessorRegistrationDelegate的registerBeanPostProcessors方法,
        int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount)); // Separate between BeanPostProcessors that implement PriorityOrdered,
// Ordered, and the rest.
从注释中可以看出,在初始化BeanPostProcessorChecker后,又继续初始化高优先级的,有顺序要求的,然后是剩下的BeanPostProcessor。
往下看:
        // First, register the BeanPostProcessors that implement PriorityOrdered.
sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors); // Next, register the BeanPostProcessors that implement Ordered.
List<BeanPostProcessor> orderedPostProcessors = new ArrayList<>();
for (String ppName : orderedPostProcessorNames) {
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
orderedPostProcessors.add(pp);
if (pp instanceof MergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);
}
}
sortPostProcessors(orderedPostProcessors, beanFactory);
registerBeanPostProcessors(beanFactory, orderedPostProcessors); // Now, register all regular BeanPostProcessors.
在初始化高优先的BeanPostProcessor后,开始load带有顺序条件的BeanPostProcessor,准备初始化。
回到最开始,我们的MethodValidationPostProcessor的父类实现了Ordered接口。故也在这个for循环的加载过程中load进来,此时,在加载的时候出现问题。
在如下代码块中
@Configuration
public class ConfigService implements WebMvcConfigurer {
@Resource
private LogService logService; @Bean
public MethodValidationPostProcessor methodValidationPostProcessor() {
return new MethodValidationPostProcessor();
}
}
我们注入了业务定义的bean,而这些bean是由最低优先级的BeanPostProcessor来加载并完成初始化的。但此时,为了加载其中的MethodValidationPostProcessor,导致不得不优先装载低优先级bean,此时,aop处理器,数据库处理器等都未完成装载,故由这部分业务bean牵扯到的相关逻辑的aop初始化,注解事务初始化,都事实上失败了。但spring就提示了一个INFO级别的提示,然后剩下的bean由最低优先级的BeanPostProcessor正常处理。
 
问题找到后,解决的方式很简单,由框架层初始化的bean,不要牵扯到业务层。不然即便初始化成功,也会导致一些模块因为顺序的缘故,未完成合适的处理流程,比如aop。
针对我这里的问题,如下解决:
@Configuration
public class MethodValidation { @Bean
public MethodValidationPostProcessor methodValidationPostProcessor() {
return new MethodValidationPostProcessor();
}
}
重新创建一个类,单独初始化此类即可。 

记一次Spring配置事故的更多相关文章

  1. 记一次 Spring 事务配置踩坑记

    记一次 Spring 事务配置踩坑记 问题描述:(SpringBoot + MyBatisPlus) 业务逻辑伪代码如下.理论上,插入数据 t1 后,xxService.getXxx() 方法的查询条 ...

  2. Spring配置c3p0数据源时出错报:java.lang.NoClassDefFoundError: com/mchange/v2/ser/Indirector

    今天在使用Spring配置c3p0数据源时,使用的数据库是mysql,服务器是tomcat,运行时报了一个 java.lang.NoClassDefFoundError: com/mchange/v2 ...

  3. spring配置详解

    1.前言 公司老项目的后台,均是基于spring框架搭建,其中还用到了log4j.jar等开源架包.在新项目中,则是spring和hibernate框架均有使用,利用了hibernate框架,来实现持 ...

  4. Spring配置汇总

    现在主流的JavaWeb应用几乎都会用到Spring,以下是Spring的配置,以及结合Web的SpringMVC配置的汇总. jar包的引入 与Web项目集成 Spring配置文件 SpringMV ...

  5. spring配置属性的两种方式

    spring配置属性有两种方式,第一种方式通过context命名空间中的property-placeholder标签 <context:property-placeholder location ...

  6. 解决eclipse spring配置报错:cvc-elt.1: Cannot find the declaration of element

    解决eclipse spring配置报错:cvc-elt.1: Cannot find the declaration of element 'beans'.Referenced file conta ...

  7. memcached 学习 1—— memcached+spring配置

    memcached 学习目录: memcached 学习 1—— memcached+spring配置 这几天自己搭建项目环境,解决问题如下: 有关常见的配置这里没有列出,中间遇到的搭建问题比较顺利g ...

  8. 解决spring配置中的bean类型的问题:BeanNotOfRequiredTypeException

    解决spring配置中的bean类型的问题:BeanNotOfRequiredTypeException这个问题出现的原因:一般在使用annotation的方式注入spring的bean 出现的,具体 ...

  9. spring配置中,properties文件以及xml文件配置问题

    spring方便我们的项目快速搭建,功能强大,自然也会是体系复杂! 这里说下配置文件properties管理的问题. 一些不涉及到代码逻辑,仅仅只是配置数据,可以放在xxxx.properties文件 ...

随机推荐

  1. #20155319 2016-2017-2 《Java程序设计》第3周学习总结

    20155319 2016-2017-2 <Java程序设计>第3周学习总结 教材学习内容总结 第三周的学习量还是很大的,需要学习的内容更难了而且 量也变多了,所以投入了更多的时间到Jav ...

  2. 2017-2018-1 20155321 《信息安全系统设计基础》课堂实践——实现mypwd

    2017-2018-1 20155321 <信息安全系统设计基础>课堂实践--实现mypwd 学习pwd命令 pwd命令:输出当前工作目录的绝对路径 还可通过man pwd具体查看pwd的 ...

  3. 【转载】C/C++杂记:深入理解数据成员指针、函数成员指针

    原文:C/C++杂记:深入理解数据成员指针.函数成员指针 1. 数据成员指针 对于普通指针变量来说,其值是它所指向的地址,0表示空指针.而对于数据成员指针变量来说,其值是数据成员所在地址相对于对象起始 ...

  4. day6 RHCE

    17.创建一个脚本 在server0上创建一个名为/root/foo.sh的脚本,让其提供下列特性: 当运行/root/foo.sh redhat,输出fedora 当运行/root/foo.sh f ...

  5. 【LG3206】[HNOI2010]城市建设

    [LG3206][HNOI2010]城市建设 题面 洛谷 题解 有一种又好想.码得又舒服的做法叫线段树分治+\(LCT\) 但是因为常数过大,无法跑过此题. 所以这里主要介绍另外一种玄学\(cdq\) ...

  6. 通过java反射机制获取该类的所有属性类型、值

    转自:http://blog.csdn.net/sd4000784/article/details/7448221 方法使用了这俩个包下的 field 和method import Java.lang ...

  7. sqlserver安装遇到的问题——1

    SQL Server安装过无数次,今天第一次遇到这样的问题 一.问题消息复制出来是这样的 TITLE: Microsoft SQL Server 2008 R2 安装程序--------------- ...

  8. MySQL数据库--连接

    MySQL数据库的概念: MySQL数据库,包括客户端和服务端.客户端就是操作数据库的终端(命令行.navicat),服务端就是安装有MySQL软件的主机(本机或者服务器),MySQL数据库的端口一般 ...

  9. 【实用】巧用For xml 生成HTML代码

    可以利用SQL的For xml直接生成HTML结构,比如我想生成如下结构: <li> <img src="..."/> <input type=&qu ...

  10. 构建树形结构数据(全部构建,查找构建)C#版

    摘要: 最近在做任务管理,任务可以无限派生子任务且没有数量限制,前端采用Easyui的Treegrid树形展示控件. 一.遇到的问题 获取全部任务拼接树形速度过慢(数据量大约在900条左右)且查询速度 ...