TransactionTest
public class TransactionTest {
public static void main(String[] args) {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
applicationContext.register(TransactionConfig.class);
applicationContext.refresh();
}
}
TransactionConfig
@Configuration
@PropertySource("classpath:dbconfig.properties")
@EnableTransactionManagement
public class TransactionConfig {
@Value("${jdbc.driverClassName}")
private String driverClassname;
@Value("${jdbc.url}")
private String url;
@Value("${jdbc.username}")
private String username;
@Value("${jdbc.password}")
private String password;
@Bean
public DataSource dataSource() {
DruidDataSource data = new DruidDataSource();
data.setDriverClassName(driverClassname);
data.setUrl(url);
data.setUsername(username);
data.setPassword(password);
return data;
}
@Bean
public JdbcTemplate jdbcTemplate(DataSource dataSource) {
return new JdbcTemplate(dataSource);
}
@Bean
public BookDao bookDao() {
return new BookDao();
}
@Bean
public BookService bookService() {
bookDao();
return new BookService();
}
@Bean
public PlatformTransactionManager transactionManager(DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
}
BookService
public class BookService {
@Autowired
BookDao bookDao;
public BookDao getBookDao() {
return bookDao;
}
public void setBookDao(BookDao bookDao) {
this.bookDao = bookDao;
}
/**
* 结账:传入哪个用户买了哪本书
* @param username
* @param id
*/
// @Transactional(propagation = Propagation.REQUIRED)
public void checkout(String username,int id){
bookDao.updateStock(id);
int price = bookDao.getPrice(id);
bookDao.updateBalance(username,price);
// try{
// for (int i = 1 ;i>=0 ;i--)
// System.out.println(10/i);
// }catch (Exception e){
// System.out.println("...............");
// }
}
}
BookDao
public class BookDao {
@Autowired
JdbcTemplate jdbcTemplate;
public JdbcTemplate getJdbcTemplate() {
return jdbcTemplate;
}
public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
/**
* 减去某个用户的余额
* @param userName
* @param price
*/
// @Transactional(propagation = Propagation.SUPPORTS)
public void updateBalance(String userName,int price){
String sql = "update account set balance=balance-? where username=?";
// for (int i = 0; i <2 ; i++) {
// int a = 1/i;
// }
jdbcTemplate.update(sql,price,userName);
}
/**
* 按照图书的id来获取图书的价格
* @param id
* @return
*/
@Transactional(propagation = Propagation.REQUIRED)
public int getPrice(int id){
String sql = "select price from book where id=?";
return jdbcTemplate.queryForObject(sql,Integer.class,id);
}
/**
* 减库存,减去某本书的库存
* @param id
*/
@Transactional(propagation = Propagation.REQUIRED)
public void updateStock(int id){
String sql = "update book_stock set stock=stock-1 where id=?";
jdbcTemplate.update(sql,id);
for (int i = 1 ;i>=0 ;i--)
System.out.println(10/i);
}
public void test(){
updateStock(1);
}
}
ConfigurationClassPostProcessor加载到DefaultListableBeanFactory的beanDefinitionMap和beanDefinitionNames
registerBeanDefinition:998, DefaultListableBeanFactory (org.springframework.beans.factory.support)
registerBeanDefinition:323, GenericApplicationContext (org.springframework.context.support)
registerPostProcessor:216, AnnotationConfigUtils (org.springframework.context.annotation)
registerAnnotationConfigProcessors:166, AnnotationConfigUtils (org.springframework.context.annotation)
registerAnnotationConfigProcessors:137, AnnotationConfigUtils (org.springframework.context.annotation)
<init>:88, AnnotatedBeanDefinitionReader (org.springframework.context.annotation)
<init>:71, AnnotatedBeanDefinitionReader (org.springframework.context.annotation)
<init>:66, AnnotationConfigApplicationContext (org.springframework.context.annotation)
main:13, TransactionTest (com.study.spring.tx.annotation)
TransactionConfig加载到DefaultListableBeanFactory的beanDefinitionMap和beanDefinitionNames
registerBeanDefinition:998, DefaultListableBeanFactory (org.springframework.beans.factory.support)
registerBeanDefinition:323, GenericApplicationContext (org.springframework.context.support)
registerBeanDefinition:164, BeanDefinitionReaderUtils (org.springframework.beans.factory.support)
doRegisterBean:285, AnnotatedBeanDefinitionReader (org.springframework.context.annotation)
registerBean:147, AnnotatedBeanDefinitionReader (org.springframework.context.annotation)
register:137, AnnotatedBeanDefinitionReader (org.springframework.context.annotation)
register:162, AnnotationConfigApplicationContext (org.springframework.context.annotation)
main:14, TransactionTest (com.study.spring.tx.annotation)
@EnableTransactionManagement注解讲解
先看下该注解的结构
最终实现了ImportSelector,该类的解析步骤如下:
processImports:568, ConfigurationClassParser (org.springframework.context.annotation)
doProcessConfigurationClass:311, ConfigurationClassParser (org.springframework.context.annotation)
processConfigurationClass:250, ConfigurationClassParser (org.springframework.context.annotation)
parse:207, ConfigurationClassParser (org.springframework.context.annotation)
parse:175, ConfigurationClassParser (org.springframework.context.annotation)
processConfigBeanDefinitions:320, ConfigurationClassPostProcessor (org.springframework.context.annotation)
postProcessBeanDefinitionRegistry:237, ConfigurationClassPostProcessor (org.springframework.context.annotation)
invokeBeanDefinitionRegistryPostProcessors:280, PostProcessorRegistrationDelegate (org.springframework.context.support)
invokeBeanFactoryPostProcessors:96, PostProcessorRegistrationDelegate (org.springframework.context.support)
invokeBeanFactoryPostProcessors:707, AbstractApplicationContext (org.springframework.context.support)
refresh:533, AbstractApplicationContext (org.springframework.context.support)
main:15, TransactionTest (com.study.spring.tx.annotation)
最终经过这一步跳转到TransactionManagementConfigurationSelector的selectImports方法:
selectImports:50, TransactionManagementConfigurationSelector (org.springframework.transaction.annotation)
selectImports:78, AdviceModeImportSelector (org.springframework.context.annotation)
processImports:581, ConfigurationClassParser (org.springframework.context.annotation)
doProcessConfigurationClass:311, ConfigurationClassParser (org.springframework.context.annotation)
processConfigurationClass:250, ConfigurationClassParser (org.springframework.context.annotation)
parse:207, ConfigurationClassParser (org.springframework.context.annotation)
parse:175, ConfigurationClassParser (org.springframework.context.annotation)
processConfigBeanDefinitions:320, ConfigurationClassPostProcessor (org.springframework.context.annotation)
postProcessBeanDefinitionRegistry:237, ConfigurationClassPostProcessor (org.springframework.context.annotation)
invokeBeanDefinitionRegistryPostProcessors:280, PostProcessorRegistrationDelegate (org.springframework.context.support)
invokeBeanFactoryPostProcessors:96, PostProcessorRegistrationDelegate (org.springframework.context.support)
invokeBeanFactoryPostProcessors:707, AbstractApplicationContext (org.springframework.context.support)
refresh:533, AbstractApplicationContext (org.springframework.context.support)
main:15, TransactionTest (com.study.spring.tx.annotation)
return new String[] {AutoProxyRegistrar.class.getName(),
ProxyTransactionManagementConfiguration.class.getName()};
这两个类返回赋值给importClassNames:
AutoProxyRegistrar执行
AutoProxyRegistrar的类结构
public class AutoProxyRegistrar implements ImportBeanDefinitionRegistrar
public interface ImportBeanDefinitionRegistrar
ParserStrategyUtils.instantiateClass用来实例化
configClass.addImportBeanDefinitionRegistrar(registrar, currentSourceClass.getMetadata());
public void addImportBeanDefinitionRegistrar(ImportBeanDefinitionRegistrar registrar, AnnotationMetadata importingClassMetadata) {
this.importBeanDefinitionRegistrars.put(registrar, importingClassMetadata);
}
ProxyTransactionManagementConfiguration执行
ProxyTransactionManagementConfiguration的类结构
@Configuration(proxyBeanMethods = false)
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public class ProxyTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration
@Configuration
public abstract class AbstractTransactionManagementConfiguration implements ImportAware
public interface ImportAware extends Aware
public interface Aware
该类和父类上有@Configuration注解,因此需要继续执行:processConfigurationClass(candidate.asConfigClass(configClass), exclusionFilter);
ProxyTransactionManagementConfiguration 在这里被添加进configurationClasses
TransactionConfig继续解析:TransactionConfig有五个@bean修饰的方法:
这里被添加;
TransactionConfig解析完毕也会被添加进configurationClasses。
public void enhanceConfigurationClasses(ConfigurableListableBeanFactory beanFactory) {
Map<String, AbstractBeanDefinition> configBeanDefs = new LinkedHashMap<>();
for (String beanName : beanFactory.getBeanDefinitionNames()) {
BeanDefinition beanDef = beanFactory.getBeanDefinition(beanName);
Object configClassAttr = beanDef.getAttribute(ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE);
AnnotationMetadata annotationMetadata = null;
MethodMetadata methodMetadata = null;
if (beanDef instanceof AnnotatedBeanDefinition) {
AnnotatedBeanDefinition annotatedBeanDefinition = (AnnotatedBeanDefinition) beanDef;
annotationMetadata = annotatedBeanDefinition.getMetadata();
methodMetadata = annotatedBeanDefinition.getFactoryMethodMetadata();
}
if ((configClassAttr != null || methodMetadata != null) && beanDef instanceof AbstractBeanDefinition) {
// Configuration class (full or lite) or a configuration-derived @Bean method
// -> eagerly resolve bean class at this point, unless it's a 'lite' configuration
// or component class without @Bean methods.
AbstractBeanDefinition abd = (AbstractBeanDefinition) beanDef;
if (!abd.hasBeanClass()) {
boolean liteConfigurationCandidateWithoutBeanMethods =
(ConfigurationClassUtils.CONFIGURATION_CLASS_LITE.equals(configClassAttr) &&
annotationMetadata != null && !ConfigurationClassUtils.hasBeanMethods(annotationMetadata));
if (!liteConfigurationCandidateWithoutBeanMethods) {
try {
abd.resolveBeanClass(this.beanClassLoader);
}
catch (Throwable ex) {
throw new IllegalStateException(
"Cannot load configuration class: " + beanDef.getBeanClassName(), ex);
}
}
}
}
if (ConfigurationClassUtils.CONFIGURATION_CLASS_FULL.equals(configClassAttr)) {
if (!(beanDef instanceof AbstractBeanDefinition)) {
throw new BeanDefinitionStoreException("Cannot enhance @Configuration bean definition '" +
beanName + "' since it is not stored in an AbstractBeanDefinition subclass");
}
else if (logger.isInfoEnabled() && beanFactory.containsSingleton(beanName)) {
logger.info("Cannot enhance @Configuration bean definition '" + beanName +
"' since its singleton instance has been created too early. The typical cause " +
"is a non-static @Bean method with a BeanDefinitionRegistryPostProcessor " +
"return type: Consider declaring such methods as 'static'.");
}
configBeanDefs.put(beanName, (AbstractBeanDefinition) beanDef);
}
}
if (configBeanDefs.isEmpty()) {
// nothing to enhance -> return immediately
return;
}
ConfigurationClassEnhancer enhancer = new ConfigurationClassEnhancer();
for (Map.Entry<String, AbstractBeanDefinition> entry : configBeanDefs.entrySet()) {
AbstractBeanDefinition beanDef = entry.getValue();
// If a @Configuration class gets proxied, always proxy the target class
beanDef.setAttribute(AutoProxyUtils.PRESERVE_TARGET_CLASS_ATTRIBUTE, Boolean.TRUE);
// Set enhanced subclass of the user-specified bean class
Class<?> configClass = beanDef.getBeanClass();
Class<?> enhancedClass = enhancer.enhance(configClass, this.beanClassLoader);
if (configClass != enhancedClass) {
if (logger.isTraceEnabled()) {
logger.trace(String.format("Replacing bean definition '%s' existing class '%s' with " +
"enhanced class '%s'", entry.getKey(), configClass.getName(), enhancedClass.getName()));
}
beanDef.setBeanClass(enhancedClass);
}
}
}
执行完enhanceConfigurationClasses之后,@Configuration注解修饰的类会把class转为代理之后的:
执行完此时的bean定义:
完整对象:
事务的处理: