Spring源码-从源码层面讲解注解配置的声明式事务

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定义:
在这里插入图片描述
完整对象:
在这里插入图片描述

事务的处理:

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值