深入了解 Spring 中的事务(从核心注解和类入手)

9 篇文章 0 订阅
2 篇文章 0 订阅

「七剑下天山」

一:@EnableTransactionManagement

二:@Transactional

三:@TransactionEventListener

四:TransactionTemplate

五:DataSourceUtils

六:TransactionSynchronizationManager

七:TransactionAwareDataSourceProxy

1 @EnableTransactionManagement

1.1 作用

此注解是 Spring 支持注解事务配置的标志。表明 Spring 开启注解事务配置的支持。是注解驱动开发事务配置的必备注解。

1.2 源码

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(TransactionManagementConfigurationSelector.class)
public @interface EnableTransactionManagement {
    /**
     * 指定基于目标类代理还是基于接口代理。
     * 默认采用JDK官方的基于接口代理。
     * @return
     */
    boolean proxyTargetClass() default false;


    /**
     * 指定事务通知是如何执行的。默认是通过代理方式执行的。
     * 如果是同一个类中调用的话,请采用AdviceMode.ASPECTJ
     * @return
     */
    AdviceMode mode() default AdviceMode.PROXY;


    /**
     * 指示在特定连接点应用多个通知时事务处理的执行顺序。
     * 默认值是:最低优先级(Integer.MAX_VALUE)
     * @return
     */
    int order() default Ordered.LOWEST_PRECEDENCE;
}

1.3 源码分析

  • @EnableTransactionManagement 通过在 @Import 注解中传入 TransactionManagementConfigurationSelector 类,会给容器中导入两个组件:

    • AutoProxyRegistrar

    • ProxyTransactionManagementConfiguration

  • AutoProxyRegistrar:给容器中注册一个 InfrastructureAdvisorAutoProxyCreator 组件;利用后置处理器机制在对象创建以后,包装对象,返回一个代理对象(增强器),代理对象执行方法利用拦截器链进行调用。

  • ProxyTransactionManagementConfiguration 使用 @Configuration 注解修饰,表明是一个配置类。

    • TransactionInterceptor;保存了事务属性信息,事务管理器;

    • TransactionInterceptor 本身是一个 MethodInterceptor,MethodInterceptor 在 spring-aop 的课程中已经分析过了。在目标方法执行的时候,会 getAdvisors() 获取拦截器链,并执行拦截器链,当只有事务拦截器时:

      1)先获取事务相关的属性

      2)再获取 PlatformTransactionManager,如果事先没有添加指定任何 transactionmanger,最终会从容器中按照类型获取一个 PlatformTransactionManager;

      3)执行目标方法

      如果正常,利用事务管理器,提交事务

      如果异常,获取到事务管理器,利用事务管理回滚操作;

    • transactionAdvisor 方法:给容器中注册事务增强器 transactionAdvisor;

    • transactionAttributeSource 方法:创建了一个注解事务的属性解析对象

    • transactionInterceptor 方法:返回值是:事务拦截器 transactionInterceptor:

 

2 @Transactional

2.1 作用

此注解是 Spring 注解配置事务的核心注解,无论是注解驱动开发还是注解和 XML 混合开发,只有涉及配置事务采用注解的方式,都需要使用此注解。

通过源码我们看到,该注解可以出现在接口上,类上和方法上。分别表明:

  • 接口上:当前接口的所有实现类中重写接口的方法有事务支持。

  • 类上:当前类中所有方法有事务支持。

  • 方法上:当前方法有事务的支持。

优先级:方法上 > 类上 > 接口上。

2.2 源码

@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface Transactional {
    /**
     * 指定事务管理器的唯一标识
     */
    @AliasFor("transactionManager") String value() default "";


    /**
     * 指定事务管理器的唯一标识
     */
    @AliasFor("value") String transactionManager() default "";


    /**
     * 指定事务的传播行为
     */
    Propagation propagation() default Propagation.REQUIRED;


    /**
     * 指定事务的隔离级别
     */
    Isolation isolation() default Isolation.DEFAULT;


    /**
     * 指定事务的超时时间
     */
    int timeout() default TransactionDefinition.TIMEOUT_DEFAULT;


    /**
     * 指定事务是否只读
     */
    boolean readOnly() default false;


    /**
     * 通过指定异常类的字节码,限定事务在特定情况下回滚
     */
    Class<? extends Throwable>[] rollbackFor() default {};


    /**
     * 通过指定异常类的全限定类名,限定事务在特定情况下回滚
     */
    String[] rollbackForClassName() default {};


    /**
     * 通过指定异常类的字节码,限定事务在特定情况下不回滚
     */
    Class<? extends Throwable>[] noRollbackFor() default {};


    /**
     * 通过指定异常类的全限定类名,限定事务在特定情况下不回滚
     */
    String[] noRollbackForClassName() default {};
}

2.3 源码分析

2.3.1 在 @EnableTransactionManagement 注解中,有一个导入器:

TransactionManagementConfigurationSelector,导入器中在 AdiviceMode 为默认值 PROXY 时,往

容器中注入了两个bean对象,AutoProxyRegistrar 和 ProxyTransactionManagementConfiguration。

// 通过 @Import注解,Spring 定义了一个事务管理配置类的导入器。
@Import(TransactionManagementConfigurationSelector.class) 
public @interface EnableTransactionManagement { 
  //其余代码略 
}

2.3.2 ProxyTransactionManagementConfiguration 类中的一个方法:

@Bean 
@Role(BeanDefinition.ROLE_INFRASTRUCTURE) 
public TransactionAttributeSource transactionAttributeSource() { 
  //创建了一个注解事务的属性解析对象 
  return new AnnotationTransactionAttributeSource(); 
}

2.3.3 AnnotationTransactionAttributeSource 类的实例化

public class AnnotationTransactionAttributeSource extends AbstractFallbackTransactionAttributeSource implements Serializable {
    /**
     * 默认构造函数
     */
    public AnnotationTransactionAttributeSource() {
        this(true);
    }


    /**
     * 带参构造(表明是否为public方法)
     */
    public AnnotationTransactionAttributeSource(boolean publicMethodsOnly) {
        this.publicMethodsOnly = publicMethodsOnly;
        //判断是不是jta或者是ejp
        if (jta12Present || ejb3Present) {
            this.annotationParsers = new LinkedHashSet<>(4);
            this.annotationParsers.add(new SpringTransactionAnnotationParser());
            //jta
            if (jta12Present) {
                this.annotationParsers.add(new
                        JtaTransactionAnnotationParser());
            }
            //ejp
            if (ejb3Present) {
                this.annotationParsers.add(new
                        Ejb3TransactionAnnotationParser());
            }
        } else {
            //当都不是的时候,构建一个SpringTransactionAnnotationParser(事务注解解析器)
            this.annotationParsers = Collections.singleton(new
                    SpringTransactionAnnotationParser());
        }
    }
}

2.3.4 SpringTransactionAnnotationParser 的注解解析:

public class SpringTransactionAnnotationParser implements TransactionAnnotationParser, Serializable {
    /**
     * 根据传入被注解的元素解析。
     * 可以是Method,Field,Class,Package,Construct等等。
     */
    @Override
    @Nullable
    public TransactionAttribute parseTransactionAnnotation(AnnotatedElement element) {
        AnnotationAttributes attributes = AnnotatedElementUtils.findMergedAnnotationAttributes(element, Transactional.class, false, false);
        if (attributes != null) { //调用根据传入注解属性解析
            return parseTransactionAnnotation(attributes);
        } else {
            return null;
        }
    }


    /**
     * 根据传入注解解析
     */
    public TransactionAttribute parseTransactionAnnotation(Transactional ann) {
        return parseTransactionAnnotation(AnnotationUtils.getAnnotationAttributes(ann, false, false));
    }


    /**
     * 根据传入的注解属性解析
     */
    protected TransactionAttribute parseTransactionAnnotation(AnnotationAttributes
                                                                      attributes) {
        RuleBasedTransactionAttribute rbta = new RuleBasedTransactionAttribute();
        Propagation propagation = attributes.getEnum("propagation");
        rbta.setPropagationBehavior(propagation.value());
        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"));
        List<RollbackRuleAttribute> rollbackRules = new ArrayList<>();
        for (Class<?> rbRule : attributes.getClassArray("rollbackFor")) {
            rollbackRules.add(new RollbackRuleAttribute(rbRule));
        }
        for (String rbRule : attributes.getStringArray("rollbackForClassName")) {
            rollbackRules.add(new RollbackRuleAttribute(rbRule));
        }
        for (Class<?> rbRule : attributes.getClassArray("noRollbackFor")) {
            rollbackRules.add(new NoRollbackRuleAttribute(rbRule));
        }
        for (String rbRule : attributes.getStringArray("noRollbackForClassName")) {
            rollbackRules.add(new NoRollbackRuleAttribute(rbRule));
        }
        rbta.setRollbackRules(rollbackRules);
        return rbta;
    }
    //其余代码略
}

 

3 @TransactionEventListener

3.1 作用

它是 spring 在 4.2 版本之后加入的注解。用于配置一个事务的事件监听器。使我们在事务提交和回滚前后可以做一些额外的功能。

例如:对事务执行监控,执行中同步做一些操作等等。

3.2 使用示例

自定义事件类:

public class MyApplicationEvent extends ApplicationEvent {
    public MyApplicationEvent(Object source) {
        super(source);
    }
}

自定义监听类:

@Component
@Slf4j
public class MyTransactionEventListener {
    @TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT)
    public void doSomething(MyApplicationEvent event) {
        Map map = (Map) event.getSource();
        log.info("事务提交后执行===>转出账户:" + map.get("sourceName") + ",转入账户:" + map.get("targetName") + ",转账金额:" + map.get("money"));
    }


    @TransactionalEventListener(phase = TransactionPhase.AFTER_ROLLBACK)
    public void otherSomething(MyApplicationEvent event) {
        Map map = (Map) event.getSource();
        log.info("事务回滚后执行===>转出账户:" + map.get("sourceName") + ",转入账户:" + map.get("targetName") + ",转账金额:" + map.get("money"));
    }
}

业务层:

@Service
public class AccountServiceImpl implements AccountService {
    @Autowired
    private AccountDao accountDao;
    @Autowired
    private ApplicationEventPublisher applicationEventPublisher;


    @Override
    @Transactional(rollbackFor = Exception.class)
    public void transfer(String sourceName, String targetName, Double money) {
        try {
            //1.根据名称查询转出账户
            Account source = accountDao.findByName(sourceName);
            //2.根据名称查询转入账户
            Account target = accountDao.findByName(targetName);
            //3.转出账户减钱
            source.setMoney(source.getMoney() - money);
            //4.转入账户加钱
            target.setMoney(target.getMoney() + money);
            accountDao.update(source); 
            // 模拟转账异常
            int i = 1 / 0; 
            //6.更新转入账户
            accountDao.update(target);
        } finally {
            Map<String, Object> map = new HashMap<>();
            map.put("sourceName", sourceName);
            map.put("targetName", targetName);
            map.put("money", money);
            // 发布自定义事件(此处可以发布多个事件,如邮件通知、短信通知等,利用自定义监听器实现代码解耦)
            applicationEventPublisher.publishEvent(new MyApplicationEvent(map));
        }
    }
}

3.3 源码

@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@EventListener
public @interface TransactionalEventListener {
    /**
     * 指定事务监听器的执行是在何时。
     * 取值有:
     *      事务提交之前
     *      事务提交之后(默认值)
     *      事务回滚之后
     *      事务执行完成之后
     */
    TransactionPhase phase() default TransactionPhase.AFTER_COMMIT;


    /**
     * 若没有事务的时候,对应的event是否已经执行
     * 默认值为false表示没事务就不执行了
     */
    boolean fallbackExecution() default false;


    /**
     * 指定事件类的字节码
     */
    @AliasFor(annotation = EventListener.class, attribute = "classes") Class<?>[] value() default {};


    /**
     * 它和value属性的作用是一样的
     */
    @AliasFor(annotation = EventListener.class, attribute = "classes") Class<?>[] classes() default {};


    /**
     * 用于指定执行事件处理器的条件。取值是基于Spring的el表达式编写的。
     */
    String condition() default "";
}

3.4 源码分析

3.4.1 在 IoC 容器加载时,执行 AbstractApplicationContext 的 refresh() 方法,一共十二个步骤,在执行到

// Instantiate all remaining (non-lazy-init) singletons. 
finishBeanFactoryInitialization(beanFactory);//触发其他单例bean的加载

3.4.2 AbstractApplicationContext 的 finishBeanFactoryInitialization 方法执行时,初始化剩余的单例 bean 对象。

/**
 * 初始化剩余单例bean对象的方法
 */
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
    // 方法中的其他代码略
    // 初始化剩余单例bean对象.调用的是DefaultListableBeanFactory类中的preInstantiateSingletons方法。
    beanFactory.preInstantiateSingletons();
}

3.4.3 DefaultListableBeanFactory 类中的 preInstantiateSingletons 方法中执行了 afterSingletonsInstantiated() 方法。此方法是SmartInitializingSingleton 接口中声明的。具体实现类包含:EventListenerMethodProcessor 事件监听器方法处理器。

3.4.4 EventListenerMethodProcessor 中的 afterSingletonsInstantiated 会被执行,该方法中包含处理 bean 的方法:processBean。

3.4.5 在 processBean 方法中调用了创建事件监听器的方法 createApplicationListener。该方法是 EventListenerFactory 接口中声明的方法。

3.4.6 TransactionalEventListenerFactory 类实现了 EventListenerFactory 接口,并重写了 createApplicationListener 方法。

/**
 * 重写接口中的创建监听器方法
 */
@Override
public ApplicationListener<?> createApplicationListener(String beanName, Class<?> type, Method method) {
    return new ApplicationListenerMethodTransactionalAdapter(beanName, type, method);
}

3.4.7 ApplicationListenerMethodTransactionalAdapter 的实例化。至此,解析 TransactionalEventListener 注解的过程完成。

/**
 * 构造函数
 */
public ApplicationListenerMethodTransactionalAdapter(String beanName, Class<?> targetClass, Method method) {
    super(beanName, targetClass, method);
    TransactionalEventListener ann = AnnotatedElementUtils.findMergedAnnotation(method, TransactionalEventListener.class);
    if (ann == null) {
        throw new IllegalStateException("No TransactionalEventListener annotation found on method: "+method);
    }
    this.annotation = ann;
}

 

4 TransactionTemplate

此类是用于编程式事务的模板对象。源码分析如下:

public class TransactionTemplate extends DefaultTransactionDefinition implements TransactionOperations, InitializingBean {
    /**
     * 定义日志组件.
     */
    protected final Log logger = LogFactory.getLog(getClass());
    /**
     * 定义事务管理器对象
     */
    @Nullable
    private PlatformTransactionManager transactionManager;


    /*** 默认构造函数 */
    public TransactionTemplate() {
    }


    /*** 通过事务管理器构建事务模板对象 */
    public TransactionTemplate(PlatformTransactionManager transactionManager) {
        this.transactionManager = transactionManager;
    }


    /*** 通过事务管理器和事务定义信息构建模板对象 */
    public TransactionTemplate(PlatformTransactionManager transactionManager, TransactionDefinition transactionDefinition) {
        super(transactionDefinition);
        this.transactionManager = transactionManager;
    }


    /*** 当使用默认构造函数构建事务模板对象时,可以通过此方法注入事务管理器 */
    public void setTransactionManager(@Nullable PlatformTransactionManager transactionManager) {
        this.transactionManager = transactionManager;
    }


    /*** 获取使用的事务管理器对象 */
    @Nullable
    public PlatformTransactionManager getTransactionManager() {
        return this.transactionManager;
    }


    /*** 判断事务管理器是否为空 */
    @Override
    public void afterPropertiesSet() {
        if (this.transactionManager == null) {
            throw new IllegalArgumentException("Property 'transactionManager' is required");
        }
    }


    /*** 编程事务控制的核心方法,重写的是TransactionOperations接口中的方法 */
    @Override
    @Nullable
    public <T> T execute(TransactionCallback<T> action) throws TransactionException {
        Assert.state(this.transactionManager != null, "No PlatformTransactionManager set"); 
        // 判断当前事务管理器是否为CallbackPreferringPlatformTransactionManager类型, 如果是的话,直接使用该接口实现类中的execute方法执行。而无需继续让 PlatformTransactionManager的实现类控制事务,当前坐标环境下它只有一个实现类:WebSphereUowTransactionManager。
        if (this.transactionManager instanceof CallbackPreferringPlatformTransactionManager) {
            return ((CallbackPreferringPlatformTransactionManager) this.transactionManager).execute(this, action);
        } else {
            // 需要借助PlatformTransactionManager的实现类控制事务。
            TransactionStatus status = this.transactionManager.getTransaction(this);
            T result;
            try {
                // 执行TransactionCallback中的doInTransaction方法,此处又是策略模式。
                // spring只提供了一个接口(还有一个抽象实现类),而具体需要事务支持的业务代 码由使用者提供。
                result = action.doInTransaction(status);
            } catch (RuntimeException | Error ex) { 
                // 当doInTransaction执行有异常时事务回滚
                rollbackOnException(status, ex);
                throw ex;
            } catch (Throwable ex) { 
                // 当doInTransaction执行有无法预知的异常时,事务回滚。
                rollbackOnException(status, ex);
                throw new UndeclaredThrowableException(ex, "TransactionCallback threw undeclared checked exception");
            }
            // 没有异常的话,事务提交
            this.transactionManager.commit(status); 
            // 返回执行结果(有可能是结果集,也有可能是影响数据库记录的行数)
            return result;
        }
    }


    /** 出现异常事务回滚 */
    private void rollbackOnException(TransactionStatus status, Throwable ex) throws TransactionException {
        Assert.state(this.transactionManager != null, "No PlatformTransactionManager set");
        logger.debug("Initiating transaction rollback on application exception", ex);
        try {
            // 执行事务管理器中提供的回滚方法。
            this.transactionManager.rollback(status);
        } catch (TransactionSystemException ex2) {
            logger.error("Application exception overridden by rollback exception", ex);
            ex2.initApplicationException(ex);
            throw ex2;
        } catch (RuntimeException | Error ex2) {
            logger.error("Application exception overridden by rollback exception", ex);
            throw ex2;
        }
    }


    /*** 重写equals方法 */
    @Override
    public boolean equals(Object other) {
        return (this == other || (super.equals(other) && (!(other instanceof TransactionTemplate) || getTransactionManager() == ((TransactionTemplate) other).getTransactionManager())));
    }
}

 

5 DataSourceUtils

Spring 中数据源的工具类。里面定义着获取连接的方法。

public abstract class DataSourceUtils {
    /*** 获取连接的方法,它本身没有任何操作而是调用了doGetConnection */
    public static Connection getConnection(DataSource dataSource) throws CannotGetJdbcConnectionException {
        try {
            // 真正获取连接的方法
            return doGetConnection(dataSource);
        } catch (SQLException ex) {
            throw new CannotGetJdbcConnectionException("Failed to obtain JDBC Connection: ", ex);
        } catch (IllegalStateException ex) {
            throw new CannotGetJdbcConnectionException("Failed to obtain JDBC Connection: " + ex.getMessage());
        }
    }


    /*** 真正从数据源中获取连接的方法 */
    public static Connection doGetConnection(DataSource dataSource) throws SQLException {
        Assert.notNull(dataSource, "No DataSource specified");
        // 通过事务同步管理器对象获取连接持有者对象
        ConnectionHolder conHolder = (ConnectionHolder) TransactionSynchronizationManager.getResource(dataSource); 
        // 当连接持有者不为null时,并且再满足连接持有者有连接或者是同步的事务其中任何一个条件, 则直接返回连接持有者的连接对象。
        // (synchronizedWithTransaction默认值为false。但是在DataSourceTransactionManager中的doBegin方法中对synchronizedWithTransaction属性赋值为 true了。
        if (conHolder != null && (conHolder.hasConnection() || conHolder.isSynchronizedWithTransaction())) {
            conHolder.requested();
            // 如果ConnectionHandle为null,则返回false,此处取反。就表示 ConnectionHandle为null时,进入if代码块中,给ConnectionHolder设置一个连接
            if (!conHolder.hasConnection()) {
                logger.debug("Fetching resumed JDBC Connection from DataSource");
                conHolder.setConnection(fetchConnection(dataSource));
            }// 返回ConnectionHolder对象中的连接
            return conHolder.getConnection();
        }
        logger.debug("Fetching JDBC Connection from DataSource");
        //如果不满足上面的条件,则从数据源中获取一个连接
        Connection con = fetchConnection(dataSource);
        //判断是否激活了事务同步器
        if (TransactionSynchronizationManager.isSynchronizationActive()) {
            try {
                // 在激活同步的条件下,如果ConnectionHolder为null就创建连接持有者对象
                ConnectionHolder holderToUse = conHolder;
                if (holderToUse == null) { //创建连接持有者对象
                    holderToUse = new ConnectionHolder(con);
                } else {
                    // 直接使用已经存在的连接持有者,并把获取到的连接填充进去
                    holderToUse.setConnection(con);
                }
                holderToUse.requested(); //注册同步器
                TransactionSynchronizationManager.registerSynchronization(new ConnectionSynchronization(holderToUse, dataSource)); //设置snchronizedWithTransaction属性为true
                holderToUse.setSynchronizedWithTransaction(true);


                // 从名称为Transactional resources的ThreadLocal中获取绑定的 Map,并把数据源和ConnectionHolder存入map中
                if (holderToUse != conHolder) {
                    TransactionSynchronizationManager.bindResource(dataSource, holderToUse);
                }
            }
        } catch(RuntimeException ex) {
            // Unexpected exception from external delegation call -> close Connection and rethrow.
            releaseConnection(con, dataSource);
            throw ex;
        }
        // 此时如果激活了事务同步管理器,则返回当前线程的连接。如果没激活,返回的就是数据源中拿 到的连接。
        return con;
    }


    /*** 从数据源中获取一个连接的方法,此时没有和线程绑定 */
    private static Connection fetchConnection(DataSource dataSource) throws SQLException {
        //从数据源中获取一个连接
        Connection con = dataSource.getConnection();
        //如果没有,则表示数据源中没有连接
        if (con == null) {
            throw new IllegalStateException("DataSource returned null from getConnection(): " + dataSource);
        }
        // 返回拿到的连接对象
        return con;
    }
    // 其余代码略
}

 

6 TransactionSynchronizationManager

事务的同步管理器类实现连接和线程绑定从而控制事务的核心类

它是个抽象类,但是没有任何子类 因为它所有的方法都是静态的。

public abstract class TransactionSynchronizationManager {
    // 定义了很多ThreadLocal
    // 应用代码随事务的声明周期绑定的对象 比如:DataSourceTransactionManager有这么做:
    // TransactionSynchronizationManager.bindResource(obtainDataSource(), txObject.getConnectionHolder());
    // TransactionSynchronizationManager.bindResource(obtainDataSource(), suspendedResources);
    // 简单理解为当前线程的数据存储中心~~~~
    // 使用的同步器,用于应用扩展
    // TransactionSynchronization同步器是最为重要的一个扩展点~~~
    // 这里是个set 所以每个线程都可以注册N多个同步器
    private static final ThreadLocal<Set<TransactionSynchronization>> synchronizations = new NamedThreadLocal<>("Transaction synchronizations");
    // 事务的名称
    private static final ThreadLocal<String> currentTransactionName = new NamedThreadLocal<>("Current transaction name");
    // 事务是否是只读
    private static final ThreadLocal<Boolean> currentTransactionReadOnly = new NamedThreadLocal<>("Current transaction read-only status");
    // 事务的隔离级别
    private static final ThreadLocal<Integer> currentTransactionIsolationLevel = new NamedThreadLocal<>("Current transaction isolation level");
    // 事务是否开启 actual:真实的
    private static final ThreadLocal<Boolean> actualTransactionActive = new NamedThreadLocal<>("Actual transaction active");


    // 判断是否是开启了和线程绑定机制。当开启了之后,我们通过DataSourceUtils获取的连接就是当 前线程的连接了。
    public static boolean isSynchronizationActive() {
        return (synchronizations.get() != null);
    }


    /*** 初始化同步器方法。此方法就是在synchronizations中设置了一个LinkedHashSet * 当然如果事务已经开启了,就不能再初始化同步器了 而是直接注册 */
    public static void initSynchronization() throws IllegalStateException {
        if (isSynchronizationActive()) {
            throw new IllegalStateException("Cannot activate transaction synchronization - already active");
        }
        logger.trace("Initializing transaction synchronization");
        synchronizations.set(new LinkedHashSet<>());
    }// 清除所有和当前线程相关的(注意:此处只是clear清除,和当前线程的绑定而已~~~) 


    public static void clear() {
        synchronizations.remove();
        currentTransactionName.remove();
        currentTransactionReadOnly.remove();
        currentTransactionIsolationLevel.remove();
        actualTransactionActive.remove();
    }
    //其余方法略 
}

 

7 TransactionAwareDataSourceProxy

这是 Spring 提供的一个数据源代理类,它继承了 DelegatingDataSource 类。

因为数据连接泄露是个很头疼的问题,Spring 框架也提供了很多种办法来避免这个问题。

比如使用 XXXTemplate,当然其背后是 DataSourceUtils。

同时还有另外一种办法,使用 TransactionAwareDataSourceProxy。

通过 TransactionAwareDataSourceProxy 对数据源代理后,数据源对象就有了事务上下文感知的能力了。

当然看源码会发现,其实它还是使用的 DataSourceUtils。

public class TransactionAwareDataSourceProxy extends DelegatingDataSource {
    /*** 暴露出来的获取连接的方法 */
    @Override
    public Connection getConnection() throws SQLException {
        return getTransactionAwareConnectionProxy(obtainTargetDataSource());
    }


    /*** 使用JDK的动态代理创建连接的代理对象 */
    protected Connection getTransactionAwareConnectionProxy(DataSource targetDataSource) {
        return (Connection) Proxy.newProxyInstance(ConnectionProxy.class.getClassLoader(), new Class<?>[]{ConnectionProxy.class}, new TransactionAwareInvocationHandler(targetDataSource));
    }


    /*** InvocationHandler的具体实现(增强的部分) */
    private class TransactionAwareInvocationHandler implements InvocationHandler {
        private final DataSource targetDataSource;
        @Nullable
        private Connection target;
        private boolean closed = false;


        public TransactionAwareInvocationHandler(DataSource targetDataSource) {
            this.targetDataSource = targetDataSource;
        }


        @Override
        @Nullable
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // Invocation on ConnectionProxy interface coming in... 
            if (method.getName().equals("equals")) {
                // Only considered as equal when proxies are identical.
                return proxy == args[0];
            } else if (method.getName().equals("hashCode")) {
                // Use hashCode of Connection proxy.
                return System.identityHashCode(proxy);
            } else if (method.getName().equals("toString")) {
                // Allow for differentiating between the proxy and the raw Connection.
                StringBuilder sb = new StringBuilder("Transaction-aware proxy for target Connection ");
                if (this.target != null) {
                    sb.append("[").append(this.target.toString()).append("]");
                } else {
                    sb.append(" from DataSource [").append(this.targetDataSource).append("]");
                }
                return sb.toString();
            } else if (method.getName().equals("unwrap")) {
                if (((Class<?>) args[0]).isInstance(proxy)) {
                    return proxy;
                }
            } else if (method.getName().equals("isWrapperFor")) {
                if (((Class<?>) args[0]).isInstance(proxy)) {
                    return true;
                }
            } else if (method.getName().equals("close")) {
                // 释放资源仍然使用的是DataSourceUtils中的方法
                DataSourceUtils.doReleaseConnection(this.target, this.targetDataSource);
                this.closed = true;
                return null;
            } else if (method.getName().equals("isClosed")) {
                return this.closed;
            }
            if (this.target == null) {
                if (this.closed) {
                    throw new SQLException("Connection handle already closed");
                }
                if (shouldObtainFixedConnection(this.targetDataSource)) {
                    this.target = DataSourceUtils.doGetConnection(this.targetDataSource);
                }
            }
            Connection actualTarget = this.target;
            if (actualTarget == null) { 
                //获取连接使用的也是DataSourceUtils中的方法
                actualTarget = DataSourceUtils.doGetConnection(this.targetDataSource);
            }
            if (method.getName().equals("getTargetConnection")) {
                return actualTarget;
            }// Invoke method on target Connection. 
            try {
                Object retVal = method.invoke(actualTarget, args);
                // If return value is a Statement, apply transaction timeout. 
                // Applies to createStatement, prepareStatement, prepareCall. 
                if (retVal instanceof Statement) {
                    DataSourceUtils.applyTransactionTimeout((Statement) retVal, this.targetDataSource);
                }
                return retVal;
            } catch (InvocationTargetException ex) {
                throw ex.getTargetException();
            } finally {
                if (actualTarget != this.target) {
                    DataSourceUtils.doReleaseConnection(actualTarget, this.targetDataSource);
                }
            }
        }
    }
    //其余代码略 
}

加油

# 精彩推荐 #

 分布式系统「全链路日志追踪」实战之 RestTemplate & Feign

 分布式任务调度框架 Elastic-Job 之动态任务发布实现详解

  小白都能看得懂的服务调用链路追踪设计与实现

   事务看完这篇你只能算入门

  [三步法] 可视化分析定位线上 JVM 问题

  从 Java 代码如何运行聊到 JVM 和对象的创建-分配-定位-布局-垃圾回收

   记一次生产频繁出现 Full GC 的 GC日志图文详解

   从源码到实战之 Spring 中的 JdbcTemplate 及策略模式自定义 JdbcTemplate 实现

 "在看"吗,赶快分享和收藏吧

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
前言 1. 简介 1.1. 概览 1.1.1. 使用场景 2. Spring 2.0和 2.5的新特性 2.1. 简介 2.2. 控制反转(IoC)容器 2.2.1. 新的bean作用域 2.2.2. 更简单的XML配置 2.2.3. 可扩展的XML编写 2.2.4. Annotation(注解)驱动配置 2.2.5. 在classpath自动搜索组件 2.3. 面向切面编程(AOP) 2.3.1. 更加简单的AOP XML配置 2.3.2. 对@AspectJ 切面的支持 2.3.3. 对bean命名pointcut( bean name pointcut element)的支持 2.3.4. 对AspectJ装载时织入(AspectJ load-time weaving)的支持 2.4. 间层 2.4.1. 在XML里更为简单的声明性事务配置 2.4.2. 对Websphere 事务管理的完整支持 2.4.3. JPA 2.4.4. 异步的JMS 2.4.5. JDBC 2.5. Web层 2.5.1. Spring MVC合理的默认值 2.5.2. Portlet 框架 2.5.3. 基于Annotation的控制器 2.5.4. Spring MVC的表单标签库 2.5.5. 对Tiles 2 支持 2.5.6. 对JSF 1.2支持 2.5.7. JAX-WS支持 2.6. 其他 2.6.1. 动态语言支持 2.6.2. 增强的测试支持 2.6.3. JMX 支持 2.6.4. 将Spring 应用程序上下文部署为JCA adapter 2.6.5. 计划任务 2.6.6. 对Java 5 (Tiger) 支持 2.7. 移植到Spring 2.5 2.7.1. 改变 2.8. 更新的样例应用 2.9. 改进的文档 I. 核心技术 3. IoC(控制反转)容器 3.1. 简介 3.2. 基本原理 - 容器和bean 3.2.1. 容器 3.2.2. 实例化容器 3.2.3. 多种bean 3.2.4. 使用容器 3.3. 依赖 3.3.1. 注入依赖 3.3.2. 依赖配置详解 3.3.3. 使用depends-on 3.3.4. 延迟初始化bean 3.3.5. 自动装配(autowire)协作者 3.3.6. 依赖检查 3.3.7. 方法注入 3.4. Bean的作用域 3.4.1. Singleton作用域 3.4.2. Prototype作用域 3.4.3. Singleton beans和prototype-bean的依赖 3.4.4. 其他作用域 3.4.5. 自定义作用域 3.5. 定制bean特性 3.5.1. 生命周期回调 3.5.2. 了解自己 3.6. bean定义的继承 3.7. 容器扩展点 3.7.1. 用BeanPostProcessor定制bean 3.7.2. 用BeanFactoryPostProcessor定制配置元数据 3.7.3. 使用FactoryBean定制实例化逻辑 3.8. The ApplicationContext 3.8.1. BeanFactory 还是 ApplicationContext? 3.8.2. 利用MessageSource实现国际化 3.8.3. 事件 3.8.4. 底层资源的访问 3.8.5. ApplicationContext在WEB应用的实例化 3.9. 粘合代码和可怕的singleton 3.10. 以J2EE RAR文件的形式部署Spring ApplicationContext 3.11. 基于注解(Annotation-based)的配置 3.11.1. @Autowired 3.11.2. 基于注解的自动连接微调 3.11.3. CustomAutowireConfigurer 3.11.4. @Resource 3.11.5. @PostConstruct 与 @PreDestroy 3.12. 对受管组件的Classpath扫描 3.12.1. @Component和更多典型化注解 3.12.2. 自动检测组件 3.12.3. 使用过滤器自定义扫描 3.12.4. 自动检测组件的命名 3.12.5. 为自动检测的组件提供一个作用域 3.12.6. 用注解提供限定符元数据 3.13. 注册一个LoadTimeWeaver 4. 资源 4.1. 简介 4.2. Resource接口 4.3. 内置 Resource 实现 4.3.1. UrlResource 4.3.2. ClassPathResource 4.3.3. FileSystemResource 4.3.4. ServletContextResource 4.3.5. InputStreamResource 4.3.6. ByteArrayResource 4.4. ResourceLoader接口 4.5. ResourceLoaderAware 接口 4.6. 把Resource作为属性来配置 4.7. Application context 和Resource 路径 4.7.1. 构造application context 4.7.2. Application context构造器资源路径的通配符 4.7.3. FileSystemResource 说明 5. 校验,数据绑定,BeanWrapper,与属性编辑器 5.1. 简介 5.2. 使用Spring的Validator接口进行校验 5.3. 从错误代码到错误信息 5.4. Bean处理和BeanWrapper 5.4.1. 设置和获取属性值以及嵌套属性 5.4.2. 内建的PropertyEditor实现 6. 使用Spring进行面向切面编程(AOP) 6.1. 简介 6.1.1. AOP概念 6.1.2. Spring AOP的功能和目标 6.1.3. AOP代理 6.2. @AspectJ支持 6.2.1. 启用@AspectJ支持 6.2.2. 声明一个切面 6.2.3. 声明一个切入点(pointcut) 6.2.4. 声明通知 6.2.5. 引入(Introduction) 6.2.6. 切面实例化模型 6.2.7. 例子 6.3. 基于Schema的AOP支持 6.3.1. 声明一个切面 6.3.2. 声明一个切入点 6.3.3. 声明通知 6.3.4. 引入 6.3.5. 切面实例化模型 6.3.6. Advisor 6.3.7. 例子 6.4. AOP声明风格的选择 6.4.1. Spring AOP还是完全用AspectJ? 6.4.2. Spring AOP使用@AspectJ还是XML? 6.5. 混合切面型 6.6. 代理机制 6.6.1. 理解AOP代理 6.7. 以编程方式创建@AspectJ代理 6.8. 在Spring应用使用AspectJ 6.8.1. 在Spring使用AspectJ进行domain object的依赖注入 6.8.2. Spring其他的AspectJ切面 6.8.3. 使用Spring IoC来配置AspectJ的切面 6.8.4. 在Spring应用使用AspectJ加载时织入(LTW) 6.9. 更多资源 7. Spring AOP APIs 7.1. 简介 7.2. Spring的切入点API 7.2.1. 概念 7.2.2. 切入点运算 7.2.3. AspectJ切入点表达式 7.2.4. 便利的切入点实现 7.2.5. 切入点的超 7.2.6. 自定义切入点 7.3. Spring的通知API 7.3.1. 通知的生命周期 7.3.2. Spring里的通知型 7.4. Spring里的Advisor API 7.5. 使用ProxyFactoryBean创建AOP代理 7.5.1. 基础 7.5.2. JavaBean属性 7.5.3. 基于JDK和CGLIB的代理 7.5.4. 对接口进行代理 7.5.5. 对进行代理 7.5.6. 使用“全局”通知器 7.6. 简化代理定义 7.7. 使用ProxyFactory通过编程创建AOP代理 7.8. 操作被通知对象 7.9. 使用“自动代理(autoproxy)”功能 7.9.1. 自动代理bean定义 7.9.2. 使用元数据驱动的自动代理 7.10. 使用TargetSource 7.10.1. 热交换目标源 7.10.2. 池化目标源 7.10.3. 原型目标源 7.10.4. ThreadLocal目标源 7.11. 定义新的Advice型 7.12. 更多资源 8. 测试 8.1. 简介 8.2. 单元测试 8.2.1. Mock对象 8.2.2. 单元测试支持 8.3. 集成测试 8.3.1. 概览 8.3.2. 使用哪个支持框架 8.3.3. 通用目标 8.3.4. JDBC测试支持 8.3.5. 常用注解 8.3.6. JUnit 3.8遗留支持 8.3.7. Spring TestContext Framework 8.3.8. PetClinic示例 8.4. 更多资源 II. 间层数据访问 9. 事务管理 9.1. 简介 9.2. 动机 9.3. 关键抽象 9.4. 使用资源同步的事务 9.4.1. 高层次方案 9.4.2. 低层次方案 9.4.3. TransactionAwareDataSourceProxy 9.5. 声明式事务管理 9.5.1. 理解Spring的声明式事务管理实现 9.5.2. 第一个例子 9.5.3. 回滚 9.5.4. 为不同的bean配置不同的事务语义 9.5.5. <tx:advice/> 有关的设置 9.5.6. 使用 @Transactional 9.5.7. 事务传播 9.5.8. 通知事务操作 9.5.9. 结合AspectJ使用 @Transactional 9.6. 编程式事务管理 9.6.1. 使用TransactionTemplate 9.6.2. 使用PlatformTransactionManager 9.7. 选择编程式事务管理还是声明式事务管理 9.8. 与特定应用服务器集成 9.8.1. IBM WebSphere 9.8.2. BEA WebLogic 9.8.3. Oracle OC4J 9.9. 常见问题的解决方法 9.9.1. 对一个特定的 DataSource 使用了错误的事务管理器 9.10. 更多的资源 10. DAO支持 10.1. 简介 10.2. 一致的异常层次 10.3. 一致的DAO支持抽象 11. 使用JDBC进行数据访问 11.1. 简介 11.1.1. 选择一种工作模式 11.1.2. Spring JDBC包结构 11.2. 利用JDBC核心控制JDBC的基本操作和错误处理 11.2.1. JdbcTemplate 11.2.2. NamedParameterJdbcTemplate 11.2.3. SimpleJdbcTemplate 11.2.4. DataSource接口 11.2.5. SQLExceptionTranslator接口 11.2.6. 执行SQL语句 11.2.7. 执行查询 11.2.8. 更新数据库 11.2.9. 获取自动生成的主键 11.3. 控制数据库连接 11.3.1. DataSourceUtils 11.3.2. SmartDataSource接口 11.3.3. AbstractDataSource 11.3.4. SingleConnectionDataSource 11.3.5. DriverManagerDataSource 11.3.6. TransactionAwareDataSourceProxy 11.3.7. DataSourceTransactionManager 11.3.8. NativeJdbcExtractor 11.4. JDBC批量操作 11.4.1. 使用JdbcTemplate进行批量操作 11.4.2. 使用SimpleJdbcTemplate进行批量操作 11.5. 通过使用SimpleJdbc简化JDBC操作 11.5.1. 使用SimpleJdbcInsert插入数据 11.5.2. 使用SimpleJdbcInsert来获取自动生成的主键 11.5.3. 指定SimpleJdbcInsert所使用的字段 11.5.4. 使用SqlParameterSource提供参数值 11.5.5. 使用SimpleJdbcCall调用存储过程 11.5.6. 声明SimpleJdbcCall使用的参数 11.5.7. 如何定义SqlParameters 11.5.8. 使用SimpleJdbcCall调用内置函数 11.5.9. 使用SimpleJdbcCall返回的ResultSet/REF Cursor 11.6. 用Java对象来表达JDBC操作 11.6.1. SqlQuery 11.6.2. MappingSqlQuery 11.6.3. SqlUpdate 11.6.4. StoredProcedure 11.6.5. SqlFunction 11.7. 参数和数据处理的基本原则 11.7.1. 为参数设置SQL型信息 11.7.2. 处理BLOB 和 CLOB对象 11.7.3. 在IN语句传入一组参数值 11.7.4. 处理复杂型的存储过程调用 12. 使用ORM工具进行数据访问 12.1. 简介 12.2. Hibernate 12.2.1. 资源管理 12.2.2. 在Spring容器创建 SessionFactory 12.2.3. The HibernateTemplate 12.2.4. 不使用回调的基于Spring的DAO实现 12.2.5. 基于Hibernate3的原生API实现DAO 12.2.6. 编程式的事务划分 12.2.7. 声明式的事务划分 12.2.8. 事务管理策略 12.2.9. 容器资源 vs 本地资源 12.2.10. 在应用服务器使用Hibernate的注意事项 12.3. JDO 12.3.1. 建立PersistenceManagerFactory 12.3.2. JdoTemplate和JdoDaoSupport 12.3.3. 基于原生的JDO API实现DAO 12.3.4. 事务管理 12.3.5. JdoDialect 12.4. Oracle TopLink 12.4.1. SessionFactory 抽象层 12.4.2. TopLinkTemplate and TopLinkDaoSupport 12.4.3. 基于原生的TopLink API的DAO实现 12.4.4. 事务管理 12.5. iBATIS SQL Maps 12.5.1. 创建SqlMapClient 12.5.2. 使用 SqlMapClientTemplate 和 SqlMapClientDaoSupport 12.5.3. 基于原生的iBATIS API的DAO实现 12.6. JPA 12.6.1. 在Spring环境建立JPA 12.6.2. JpaTemplate 和 JpaDaoSupport 12.6.3. 基于原生的JPA实现DAO 12.6.4. 异常转化 12.7. 事务管理 12.8. JpaDialect III. The Web 13. Web MVC framework Web框架 13.1. 概述 13.1.1. 与其他MVC实现框架的集成 13.1.2. Spring Web MVC框架的特点 13.2. DispatcherServlet 13.3. 控制器 13.3.1. AbstractController 和 WebContentGenerator 13.3.2. 其它的简单控制器 13.3.3. MultiActionController 13.3.4. 命令控制器 13.4. 处理器映射(handler mapping) 13.4.1. BeanNameUrlHandlerMapping 13.4.2. SimpleUrlHandlerMapping 13.4.3. 拦截器(HandlerInterceptor) 13.5. 视图与视图解析 13.5.1. 视图解析器(ViewResolver) 13.5.2. 视图解析链 13.5.3. 重定向(Rediret)到另一个视图 13.6. 本地化解析器 13.6.1. AcceptHeaderLocaleResolver 13.6.2. CookieLocaleResolver 13.6.3. SessionLocaleResolver 13.6.4. LocaleChangeInterceptor 13.7. 使用主题 13.7.1. 简介 13.7.2. 如何定义主题 13.7.3. 主题解析器 13.8. Spring对分段文件上传(multipart file upload)的支持 13.8.1. 介绍 13.8.2. 使用MultipartResolver 13.8.3. 在表单处理分段文件上传 13.9. 使用Spring的表单标签库 13.9.1. 配置 13.9.2. form标签 13.9.3. input标签 13.9.4. checkbox标签 13.9.5. checkboxes标签 13.9.6. radiobutton标签 13.9.7. radiobuttons标签 13.9.8. password标签 13.9.9. select标签 13.9.10. option标签 13.9.11. options标签 13.9.12. textarea标签 13.9.13. hidden标签 13.9.14. errors标签 13.10. 处理异常 13.11. 惯例优先原则(convention over configuration) 13.11.1. 对控制器的支持:ControllerClassNameHandlerMapping 13.11.2. 对模型的支持:ModelMap(ModelAndView) 13.11.3. 对视图的支持:RequestToViewNameTranslator 13.12. 基于注解的控制器配置 13.12.1. 建立dispatcher实现注解支持 13.12.2. 使用@Controller定义一个控制器 13.12.3. 使用@RequestMapping映射请求 13.12.4. 使用@RequestParam绑定请求参数到方法参数 13.12.5. 使用@ModelAttribute提供一个从模型到数据的链接 13.12.6. 使用@SessionAttributes指定存储在会话的属性 13.12.7. 自定义WebDataBinder初始化 13.13. 更多资源 14. 集成视图技术 14.1. 简介 14.2. JSP和JSTL 14.2.1. 视图解析器 14.2.2. 'Plain-old' JSPs versus JSTL 'Plain-old' JSP与JSTL 14.2.3. 帮助简化开发的额外的标签 14.3. Tiles 14.3.1. 需要的资源 14.3.2. 如何集成Tiles 14.4. Velocity和FreeMarker 14.4.1. 需要的资源 14.4.2. Context 配置 14.4.3. 创建模板 14.4.4. 高级配置 14.4.5. 绑定支持和表单处理 14.5. XSLT 14.5.1. 写在段首 14.5.2. 小结 14.6. 文档视图(PDF/Excel) 14.6.1. 简介 14.6.2. 配置和安装 14.7. JasperReports 14.7.1. 依赖的资源 14.7.2. 配置 14.7.3. 构造ModelAndView 14.7.4. 使用子报表 14.7.5. 配置Exporter的参数 15. 集成其它Web框架 15.1. 简介 15.2. 通用配置 15.3. JavaServer Faces 15.3.1. DelegatingVariableResolver 15.3.2. FacesContextUtils 15.4. Struts 15.4.1. ContextLoaderPlugin 15.4.2. ActionSupport Classes 15.5. Tapestry 15.5.1. 注入 Spring 托管的 beans 15.6. WebWork 15.7. 更多资源 16. Portlet MVC框架 16.1. 介绍 16.1.1. 控制器 - MVC的C 16.1.2. 视图 - MVC的V 16.1.3. Web作用范围的Bean 16.2. DispatcherPortlet 16.3. ViewRendererServlet 16.4. 控制器 16.4.1. AbstractController 和 PortletContentGenerator 16.4.2. 其它简单的控制器 16.4.3. Command控制器 16.4.4. PortletWrappingController 16.5. 处理器映射 16.5.1. PortletModeHandlerMapping 16.5.2. ParameterHandlerMapping 16.5.3. PortletModeParameterHandlerMapping 16.5.4. 增加 HandlerInterceptors 16.5.5. HandlerInterceptorAdapter 16.5.6. ParameterMappingInterceptor 16.6. 视图和它们的解析 16.7. Multipart文件上传支持 16.7.1. 使用 PortletMultipartResolver 16.7.2. 处理表单里的文件上传 16.8. 异常处理 16.9. Portlet应用的部署 IV. 整合 17. 使用Spring进行远程访问与Web服务 17.1. 简介 17.2. 使用RMI暴露服务 17.2.1. 使用RmiServiceExporter暴露服务 17.2.2. 在客户端链接服务 17.3. 使用Hessian或者Burlap通过HTTP远程调用服务 17.3.1. 为Hessian和co.配置DispatcherServlet 17.3.2. 使用HessianServiceExporter暴露你的bean 17.3.3. 在客户端连接服务 17.3.4. 使用Burlap 17.3.5. 对通过Hessian或Burlap暴露的服务使用HTTP Basic认证 17.4. 使用HTTP调用器暴露服务 17.4.1. Exposing the service object 17.4.2. 在客户端连接服务 17.5. Web Services 17.5.1. 使用JAX-RPC暴露基于servlet的web服务 17.5.2. 使用JAX-RPC访问web服务 17.5.3. 注册JAX-RPC Bean映射 17.5.4. 注册自己的JAX-RPC 处理器 17.5.5. 使用JAX-WS暴露基于servlet的web服务 17.5.6. 使用JAX-WS暴露单独web服务 17.5.7. 使用Spring支持的JAX-WS RI来暴露服务 17.5.8. 使用JAX-WS访问web服务 17.5.9. 使用XFire来暴露Web服务 17.6. JMS 17.6.1. 服务端配置 17.6.2. 客户端配置 17.7. 对远程接口不提供自动探测实现 17.8. 在选择这些技术时的一些考虑 18. Enterprise Java Beans (EJB) 集成 18.1. 简介 18.2. 访问EJB 18.2.1. 概念 18.2.2. 访问本地的无状态Session Bean(SLSB) 18.2.3. 访问远程SLSB 18.2.4. Accessing EJB 2.x SLSBs versus EJB 3 SLSBs 18.3. 使用Spring提供的辅助实现EJB组件 18.3.1. EJB 2.x base classes 18.3.2. EJB 3 注入拦截 19. JMS (Java Message Service) 19.1. 简介 19.2. 使用Spring JMS 19.2.1. JmsTemplate 19.2.2. 连接工厂 19.2.3. 目的地管理 19.2.4. 消息侦听容器 19.2.5. 事务管理 19.3. 发送消息 19.3.1. 使用消息转换器 19.3.2. SessionCallback 和 ProducerCallback 19.4. 接收消息 19.4.1. 同步接收 19.4.2. 异步接收 - 消息驱动的POJO 19.4.3. SessionAwareMessageListener接口 19.4.4. MessageListenerAdapter 19.4.5. 事务的消息处理 19.5. JCA消息端点的支持 19.6. JMS命名空间支持 20. JMX 20.1. 介绍 20.2. 将Bean暴露为JMX 20.2.1. 创建MBeanServer 20.2.2. 重用原有的MBeanServer 20.2.3. 延迟初始化的MBean 20.2.4. MBean的自动注册 20.2.5. 控制注册行为 20.3. 控制Bean的管理接口 20.3.1. MBeanInfoAssembler接口 20.3.2. 使用源码级元数据 20.3.3. 使用JDK 5.0的注解 20.3.4. 源代码级的元数据型 20.3.5. AutodetectCapableMBeanInfoAssembler接口 20.3.6. 用Java接口定义管理接口 20.3.7. 使用MethodNameBasedMBeanInfoAssembler 20.4. 控制Bean的ObjectName 20.4.1. 从Properties读取Properties 20.4.2. 使用MetadataNamingStrategy 20.4.3. <context:mbean-export/>元素 20.5. JSR-160连接器 20.5.1. 服务器端连接器 20.5.2. 客户端连接器 20.5.3. 基于Burlap/Hessian/SOAP的JMX 20.6. 通过代理访问MBean 20.7. 通知 20.7.1. 为通知注册监听器 20.7.2. 发布通知 20.8. 更多资源 21. JCA CCI 21.1. 简介 21.2. 配置CCI 21.2.1. 连接器配置 21.2.2. 在Spring配置ConnectionFactory 21.2.3. 配置CCI连接 21.2.4. 使用一个 CCI 单连接 21.3. 使用Spring的 CCI访问支持 21.3.1. 记录转换 21.3.2. CciTemplate 21.3.3. DAO支持 21.3.4. 自动输出记录生成 21.3.5. 总结 21.3.6. 直接使用一个CCI Connection接口和Interaction接口 21.3.7. CciTemplate 使用示例 21.4. 建模CCI访问为操作对象 21.4.1. MappingRecordOperation 21.4.2. MappingCommAreaOperation 21.4.3. 自动生成输出记录 21.4.4. 总结 21.4.5. MappingRecordOperation 使用示例 21.4.6. MappingCommAreaOperation 使用示例 21.5. 事务 22. Spring邮件抽象层 22.1. 简介 22.2. 使用Spring邮件抽象 22.2.1. MailSender 和 SimpleMailMessage 的基本用法 22.2.2. 使用 JavaMailSender 和 MimeMessagePreparator 22.3. 使用MimeMessageHelper 22.3.1. 发送附件和嵌入式资源(inline resources) 22.3.2. 使用模板来创建邮件内容 23. Spring的定时调度(Scheduling)和线程池(Thread Pooling) 23.1. 简介 23.2. 使用OpenSymphony Quartz 调度器 23.2.1. 使用JobDetailBean 23.2.2. 使用 MethodInvokingJobDetailFactoryBean 23.2.3. 使用triggers和SchedulerFactoryBean来包装任务 23.3. 使用JDK Timer支持 23.3.1. 创建定制的timers 23.3.2. 使用 MethodInvokingTimerTaskFactoryBean 23.3.3. 最后:使用TimerFactoryBean来设置任务 23.4. SpringTaskExecutor抽象 23.4.1. TaskExecutor接口 23.4.2. TaskExecutor型 23.4.3. 使用TaskExecutor 24. 动态语言支持 24.1. 介绍 24.2. 第一个示例 24.3. 定义动态语言支持的bean 24.3.1. 公共概念 24.3.2. JRuby beans 24.3.3. Groovy beans 24.3.4. BeanShell beans 24.4. 场景 24.4.1. Spring MVC控制器的脚本化 24.4.2. Validator的脚本化 24.5. Bits and bobs 24.5.1. AOP - 通知脚本化bean 24.5.2. 作用域 24.6. 更多的资源 25. 注解和源代码级的元数据支持 25.1. 简介 25.2. Spring的元数据支持 25.3. 注解 25.3.1. @Required 25.3.2. Spring的其它@Annotations 25.4. Jakarta Commons Attributes集成 25.5. 元数据和Spring AOP自动代理 25.5.1. 基本原理 25.5.2. 声明式事务管理 V. 示例程序 26. 演示案例 26.1. 介绍 26.2. 使用动态语言实现的Spring MVC控制器 26.2.1. 构建与部署 26.3. 使用SimpleJdbcTemplate和@Repository实现DAO 26.3.1. 域对象 26.3.2. Data Access Object 26.3.3. 构建 A. XML Schema-based configuration A.1. Introduction A.2. XML Schema-based configuration A.2.1. Referencing the schemas A.2.2. The util schema A.2.3. The jee schema A.2.4. The lang schema A.2.5. The jms schema A.2.6. The tx (transaction) schema A.2.7. The aop schema A.2.8. The context schema A.2.9. The tool schema A.2.10. The beans schema A.3. Setting up your IDE A.3.1. Setting up Eclipse A.3.2. Setting up IntelliJ IDEA A.3.3. Integration issues B. Extensible XML authoring B.1. Introduction B.2. Authoring the schema B.3. Coding a NamespaceHandler B.4. Coding a BeanDefinitionParser B.5. Registering the handler and the schema B.5.1. 'META-INF/spring.handlers' B.5.2. 'META-INF/spring.schemas' B.6. Using a custom extension in your Spring XML configuration B.7. Meatier examples B.7.1. Nesting custom tags within custom tags B.7.2. Custom attributes on 'normal' elements B.8. Further Resources C. spring-beans-2.0.dtd D. spring.tld D.1. Introduction D.2. The bind tag D.3. The escapeBody tag D.4. The hasBindErrors tag D.5. The htmlEscape tag D.6. The message tag D.7. The nestedPath tag D.8. The theme tag D.9. The transform tag E. spring-form.tld E.1. Introduction E.2. The checkbox tag E.3. The checkboxes tag E.4. The errors tag E.5. The form tag E.6. The hidden tag E.7. The input tag E.8. The label tag E.9. The option tag E.10. The options tag E.11. The password tag E.12. The radiobutton tag E.13. The radiobuttons tag E.14. The select tag E.15. The textarea tag F. Spring 2.5开发手册文化项目 F.1. 声明 F.2. 致谢 F.3. 参与人员 F.4. 项目历程 表格清单 3.1. bean定义 3.2. Autowiring modes 3.3. 依赖检查方式 3.4. Bean作用域 3.5. Feature Matrix特性表 3.6. 内置事件 3.7. 过滤器型 4.1. Resource strings 5.1. 属性示例 5.2. 内建的PropertyEditors 6.1. DefaultContextLoadTimeWeaver LoadTimeWeaversDefaultContextLoadTimeWeaver和LoadTimeWeavers接口 6.2. aspectj-weaving属性值 9.1. <tx:method/> 有关的设置 9.2. <tx:annotation-driven/> 设置 9.3. @Transactional 注解的属性 13.1. WebApplicationContext特殊的bean 13.2. DispatcherServlet初始化参数 13.3. AbstractController提供的功能 13.4. 视图解析器 13.5. CookieLocaleResolver的属性 13.6. ThemeResolver的实现 14.1. 宏定义表 14.2. JasperReports View Classes 14.3. JasperReportsMultiFormatView默认Mapping Key映射 16.1. WebApplicationContext特殊的Bean 16.2. DispatcherPortlet 的初始化参数 16.3. AbstractController提供的功能 19.1. JMS listener 元素的属性 19.2. JMS <listener-container/> 元素的属性 19.3. JMS <jca-listener-container/> 元素的属性 20.1. 注册行为 20.2. 源代码级的元数据型 20.3. 源代码级的元数据参数 21.1. Usage of Interaction execute methods 21.2. Usage of Interaction execute methods A.1. Eclipse XML editors D.1. Attributes D.2. Attributes D.3. Attributes D.4. Attributes D.5. Attributes D.6. Attributes D.7. Attributes D.8. Attributes E.1. Attributes E.2. Attributes E.3. Attributes E.4. Attributes E.5. Attributes E.6. Attributes E.7. Attributes E.8. Attributes E.9. Attributes E.10. Attributes E.11. Attributes E.12. Attributes E.13. Attributes E.14. Attributes F.1. 参与人员列表

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值