# Aware 接口# Aware 接口作用# Spring 项目中 @Value 注解失效情况判断之前很多时候都有这个疑惑,在 JavaConfig 配置 MyBatis 和 DataSource 时,总会出现 @Value 注入失败,现在知道原因了,是 MapperScannerConfigurer 的问题,它是一个 BeanFactroyPostProcessor, 且通过 @Bean 创建,所以在添加 BeanFactroyPostProcessor 步骤就会创建 JavaConfig 实例对象,为了通过工厂方法创建 MapperScannerConfigurer (即 @Bean 注解的方法), 所以这个时候就不会执行依赖注入,初始化,而是在此之后才会进行,而 JavaConfig 类已经实例化了,不会受到 BeanPostProcessor 影响了,自然也就注入失败了
失败代码 :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 @Configuration @PropertySource(value = {"classpath:dataSource.properties"}) public class JavaConfig { @Value("${driverName}") private String driverName; @Value("${url}") private String url; @Value("${user}") private String username; @Value("${password}") private String password; @Bean public DataSource dataSource () { DruidDataSource dataSource = new DruidDataSource (); dataSource.setDriverClassName(driverName); dataSource.setUrl(url); dataSource.setUsername(username); dataSource.setPassword(password); return dataSource; } @Bean public SqlSessionFactoryBean sqlSessionFactoryBean (DataSource dataSource) { SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean (); sqlSessionFactoryBean.setDataSource(dataSource); PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver (); Resource[] resources = null ; try { resources = resolver.getResources("classpath:/mapper/*.xml" ); } catch (IOException e) { throw new RuntimeException (e); } sqlSessionFactoryBean.setMapperLocations(resources); return sqlSessionFactoryBean; } @Bean public MapperScannerConfigurer mapperScannerConfigurer () { MapperScannerConfigurer mapperScannerConfigurer = new MapperScannerConfigurer (); mapperScannerConfigurer.setBasePackage("com.wong.mapper" ); return mapperScannerConfigurer; } }
解决方法之一 (手动添加):
1 2 3 4 5 6 7 8 9 10 11 12 13 public class Main { public static void main (String[] args) { GenericApplicationContext context = new GenericApplicationContext (); context.registerBean(MapperScannerConfigurer.class, beanDefinition -> beanDefinition.getPropertyValues().add("basePackage" , "com.wong.mapper" )); context.registerBean("javaConfig" , JavaConfig.class); context.refresh(); MusicCommentMapper mapper = context.getBean(MusicCommentMapper.class); for (MusicComment musicComment : mapper.getAllByCommentText()) { System.out.println(musicComment); } } }
正常情况下的执行步骤 :
1 2 3 4 5 6 7 8 9 sequenceDiagram ApplicationContext -> BeanFactoryPostProcessor : 1. 执行BeanFactoryPostProcessor ApplicationContext -> BeanPostProcessor : 2. 注册BeanPostProcessor ApplicationContext -> Java配置类 : 3. 创建和初始化 BeanPostProcessor -> Java配置类 : 3.1 依赖注入扩展(如@Value和@Autowired) BeanPostProcessor -> Java配置类 : 3.2 初始化扩展(如@PostConstruct) ApplicationContext -> Java配置类 : 2.3 执行Aware及InitializingBean Java配置类 --> ApplicationContext : 3.4 创建成功
失效情况下的执行步骤 :
1 2 3 4 5 6 7 8 9 10 11 12 sequenceDiagram participant ApplicationContext as ApplicationContext participant BeanFactoryPostProcessor as BeanFactoryPostProcessor participant BeanPostProcessor as BeanPostProcessor participant Java配置类 as Java配置类 ApplicationContext -> Java配置类 : 3. 创建和初始化 ApplicationContext -> Java配置类 : 3.1 执行Aware和InitializingBean Java配置类 --> ApplicationContext : 3.2 创建成功 ApplicationContext -> BeanFactoryPostProcessor : 1. 执行BeanFactoryPostProcessor ApplicationContext -> BeanPostProcessor : 2. 注册BeanPostProcessor