@PropertySource("classpath:tx.properties") @Configuration @ComponentScan(basePackages = "org.panrd.service") @EnableTransactionManagement public class TxConfig2 implements EnvironmentAware { public TxConfig2() { System.out.println("Txconfig2-------"); } private Environment environment; @Bean public DataSource dataSource() throws Exception { Properties props = new Properties(); props.put(DruidDataSourceFactory.PROP_URL, environment.getProperty("druid.url")); props.put(DruidDataSourceFactory.PROP_USERNAME, environment.getProperty("druid.user")); props.put(DruidDataSourceFactory.PROP_PASSWORD, environment.getProperty("druid.passwd")); return DruidDataSourceFactory.createDataSource(props); } @Bean public SqlSessionFactoryBean sqlSessionFactoryBean() throws Exception { SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean(); DataSource dataSource = dataSource(); sqlSessionFactoryBean.setDataSource(dataSource); sqlSessionFactoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:mappers/*.xml")); return sqlSessionFactoryBean; } @Bean public MapperScannerConfigurer mapperScannerConfigurer() { MapperScannerConfigurer configurer = new MapperScannerConfigurer(); configurer.setBasePackage("org.panrd.dao"); return configurer; } @Bean public PlatformTransactionManager transactionManager() throws Exception { DataSource dataSource = dataSource(); return new DataSourceTransactionManager(dataSource); } @Override public void setEnvironment(Environment environment) { this.environment = environment; } }
service方法中添加@Transactional后,运行时事务不起作用。
由于MapperScannerConfigurer实现了BeanDefinitionRegistryPostProcessor,spring启动时会优先实例化这类bean,MapperScannerConfigurer实例化的策略是factoryMethod,他的工厂类是TxConfig2,所以会去实例化TxConfig2,bean容器中存放的是普通的bean实例,即使后面调用ConfigurationClassPostProcessor来增强TxConfig2的BeanDefiniation,在finishBeanFactoryInitialization(beanFactory)方法中创建剩余的单例bean的时候,由于容器中已经存在TxConfig2的bean了,所以不会再去创建,从而导致dataSource()方法每次都是new一个新的对象,使事务失效。