(三)Springソース分析----tx事務管理
9608 ワード
Spring事務はAOP代理に基づいて完成しました.前のAOPソース分析の基礎があります.Spring事務は分かりやすいです.まずSpringの注釈版の事務配置例を見てみます.
Spring設定クラス:AOP機能を開くと同じように、事務機能も注釈@EnbaleTransaction Managementで開く必要があります.また、事務マネージャを配置する必要があります.デフォルトではDataSourceTransationManager事務管理器を使用します.
Spring設定クラス:AOP機能を開くと同じように、事務機能も注釈@EnbaleTransaction Managementで開く必要があります.また、事務マネージャを配置する必要があります.デフォルトではDataSourceTransationManager事務管理器を使用します.
@ComponentScan("ts")
@EnableTransactionManagement
@EnableAspectJAutoProxy
@Configurable
public class TsConfig {
//
@Bean
public DataSource dataSource()throws Exception{
ComboPooledDataSource dataSource = new ComboPooledDataSource();
dataSource.setUser("root");
dataSource.setPassword("w4467106");
dataSource.setDriverClass("com.mysql.jdbc.Driver");
dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/test");
dataSource.setConnectionCustomizerClassName(YourConnectionCustomizer.class.getName());
return dataSource;
}
//
@Bean
public JdbcTemplate jdbcTemplate()throws Exception{
JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource());
return jdbcTemplate;
}
//
@Bean
public PlatformTransactionManager transactionManager()throws Exception{
return new DataSourceTransactionManager(dataSource());
}
}
ここに穴があります.インターネットで事務を配置した後、異常が発生したことを発見しました.MysqlエンジンもInnoDBです.最終的にはc 3 p 0のカバンの中のCoboPooledDataSourceデータソースが発見されました.デフォルトのComplodDataSourceデータソースはオープン前にデータベース接続の自動提出をオフしません.AbstractConnection Custoomizer類を引き継ぎ、データベース接続を自動的にオフにする必要があります.public class YourConnectionCustomizer extends AbstractConnectionCustomizer {
@Override
public void onCheckOut(Connection c, String parentDataSourceIdentityToken) throws Exception {
super.onCheckOut(c, parentDataSourceIdentityToken);
c.setAutoCommit(false);
}
}
ところで、Spring事務の原理を探ってみます.事務をオープンします.@EnbaleTranscationManagementをクリックしてみると、AOPとはセットです.全部Importを通してSpringコンポーネントを導入して、期待機能を完成します.// TransactionManagementConfigurationSelector
@Import({TransactionManagementConfigurationSelector.class})
public @interface EnableTransactionManagement {
boolean proxyTargetClass() default false;
AdviceMode mode() default AdviceMode.PROXY;
int order() default 2147483647;
}
Transation Management ConfigrationSelectorコンポーネントはどのような機能を果たしていますか?ソースからSelectorを発見しました.また、2つの新しいコンポーネントAutoProxyRegistarとProxTranction Management Configrationを登録してくれました.この2つのコンポーネントの役割を分析します.public class TransactionManagementConfigurationSelector extends AdviceModeImportSelector {
public TransactionManagementConfigurationSelector() {
}
protected String[] selectImports(AdviceMode adviceMode) {
switch(adviceMode) {
case PROXY:
// adviceMode ,
return new String[]{AutoProxyRegistrar.class.getName(), ProxyTransactionManagementConfiguration.class.getName()};
case ASPECTJ:
return new String[]{"org.springframework.transaction.aspectj.AspectJTransactionManagementConfiguration"};
default:
return null;
}
}
}
AutoProxyRegistar:実は、その役割は容器に後置プロセッサを登録し、後置プロセッサ機構を利用してbeanに包装代理オブジェクトを作成し、増強器advisorを追加することです.public class AutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
private final Log logger = LogFactory.getLog(this.getClass());
............................
// AOP , AopConfigUtils
AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry);
.........
}
//
public static BeanDefinition registerAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry, Object source) {
return registerOrEscalateApcAsRequire(InfrastructureAdvisorAutoProxyCreator.class, registry, source);
}
...............
public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware {
......................
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (bean != null) {
Object cacheKey = this.getCacheKey(bean.getClass(), beanName);
if (!this.earlyProxyReferences.contains(cacheKey)) {
// AOP bean
return this.wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
}
ProxyTranction Management Configration:その役割は主に容器に事務増長器advisorを作成することであり、第一歩は増長器に事務属性リソースtransplation AttributeSourceを追加し、第二ステップは増長器に事務ブロックを追加することである.@Configuration
public class ProxyTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration {
public ProxyTransactionManagementConfiguration() {
}
//
@Bean(
name = {"org.springframework.transaction.config.internalTransactionAdvisor"}
)
@Role(2)
public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor() {
//
BeanFactoryTransactionAttributeSourceAdvisor advisor = new BeanFactoryTransactionAttributeSourceAdvisor();
//
advisor.setTransactionAttributeSource(this.transactionAttributeSource());
//
advisor.setAdvice(this.transactionInterceptor());
advisor.setOrder((Integer)this.enableTx.getNumber("order"));
return advisor;
}
}
第1段階で追加されたトランザクション属性リソース解析器Advisor()は、トランザクション解析用のTrantationTransationAttributeSource()を登録します.public TransactionAttributeSource transactionAttributeSource() {
return new AnnotationTransactionAttributeSource();
}
.........................................................
// SpringTransactionAnnotationParser
protected TransactionAttribute parseTransactionAnnotation(AnnotationAttributes attributes) {
RuleBasedTransactionAttribute rbta = new RuleBasedTransactionAttribute();
Propagation propagation = (Propagation)attributes.getEnum("propagation");
rbta.setPropagationBehavior(propagation.value());
Isolation isolation = (Isolation)attributes.getEnum("isolation");
rbta.setIsolationLevel(isolation.value());
rbta.setTimeout(attributes.getNumber("timeout").intValue());
rbta.setReadOnly(attributes.getBoolean("readOnly"));
rbta.setQualifier(attributes.getString("value"));
ArrayList rollBackRules = new ArrayList();
Class>[] rbf = attributes.getClassArray("rollbackFor");
Class[] var7 = rbf;
int var8 = rbf.length;
}
第二のステップは、Oopエージェントと同じTransationInterceptrであり、TransationInterceptorはMethodInterceptorから継承されています.public class TransactionInterceptor extends TransactionAspectSupport implements MethodInterceptor, Serializable {
public TransactionInterceptor() {
}
public TransactionInterceptor(PlatformTransactionManager ptm, Properties attributes) {
this.setTransactionManager(ptm);
this.setTransactionAttributes(attributes);
}
public TransactionInterceptor(PlatformTransactionManager ptm, TransactionAttributeSource tas) {
this.setTransactionManager(ptm);
this.setTransactionAttributeSource(tas);
}
//
public Object invoke(final MethodInvocation invocation) throws Throwable {
Class> targetClass = invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null;
// invokeWithinTransaction
return this.invokeWithinTransaction(invocation.getMethod(), targetClass, new InvocationCallback() {
public Object proceedWithInvocation() throws Throwable {
return invocation.proceed();
}
});
}
}
上記のソースコードを通じて、最終的にはプロキシのコールバック方法でinvoke WithinTransactionを実行することが分かりました.これはまず容器から事務管理器Platform Transation Managerを獲得します.事務管理器はまず事務を作成します.実行文が異常が発生したら、事務管理器を通じてロールバックします.正常に事務を提出してください.protected Object invokeWithinTransaction(Method method, Class> targetClass, final TransactionAspectSupport.InvocationCallback invocation) throws Throwable {
final TransactionAttribute txAttr = this.getTransactionAttributeSource().getTransactionAttribute(method, targetClass);
// transationManager
final PlatformTransactionManager tm = this.determineTransactionManager(txAttr);
final String joinpointIdentification = this.methodIdentification(method, targetClass, txAttr);
if (txAttr != null && tm instanceof CallbackPreferringPlatformTransactionManager) {
try {
Object result = ((CallbackPreferringPlatformTransactionManager)tm).execute(txAttr, new TransactionCallback