spring源码(事务(配置文件的加载及对象的创建))

xml配置项

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
    <context:property-placeholder location="classpath:dbconfig.properties"></context:property-placeholder>
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="username" value="${jdbc.username}"></property>
        <property name="password" value="${jdbc.password}"></property>
        <property name="url" value="${jdbc.url}"></property>
        <property name="driverClassName" value="${jdbc.driverClassName}"></property>
    </bean>
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate" >
        <constructor-arg name="dataSource" ref="dataSource"></constructor-arg>
    </bean>
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"></property>
    </bean>
    <bean id="bookService" class="com.mashibing.tx.xml.service.BookService">
        <property name="bookDao" ref="bookDao"></property>
    </bean>
    <bean id="bookDao" class="com.mashibing.tx.xml.dao.BookDao">
        <property name="jdbcTemplate" ref="jdbcTemplate"></property>
    </bean>
    <aop:config>
        <aop:pointcut id="txPoint" expression="execution(* com.mashibing.tx.xml.*.*.*(..))"/>
        <aop:advisor advice-ref="myAdvice" pointcut-ref="txPoint"></aop:advisor>
    </aop:config>
    <tx:advice id="myAdvice" transaction-manager="transactionManager">
        <tx:attributes>
            <tx:method name="checkout" propagation="REQUIRED" />
            <tx:method name="updateStock" propagation="REQUIRES_NEW" />
        </tx:attributes>
    </tx:advice>
</beans>

service层

public class BookService {

    BookDao bookDao;

    public BookDao getBookDao() {
        return bookDao;
    }

    public void setBookDao(BookDao bookDao) {
        this.bookDao = bookDao;
    }

    /**
     * 结账:传入哪个用户买了哪本书
     * @param username
     * @param id
     */
    public void checkout(String username,int id){

        try {
            bookDao.updateStock(id);
        } catch (Exception e) {
            e.printStackTrace();
        }
//        for (int i = 1 ;i>=0 ;i--)
//            System.out.println(10/i);
//        int price = bookDao.getPrice(id);
//        bookDao.updateBalance(username,price);
    }
}

dao层

public class BookDao {

    JdbcTemplate jdbcTemplate;

    public JdbcTemplate getJdbcTemplate() {
        return jdbcTemplate;
    }

    public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
        this.jdbcTemplate = jdbcTemplate;
    }

    /**
     * 减去某个用户的余额
     * @param userName
     * @param price
     */
    public void updateBalance(String userName,int price){
        String sql = "update account set balance=balance-? where username=?";
        jdbcTemplate.update(sql,price,userName);
    }

    /**
     * 按照图书的id来获取图书的价格
     * @param id
     * @return
     */
    public int getPrice(int id){
        String sql = "select price from book where id=?";
        return jdbcTemplate.queryForObject(sql,Integer.class,id);
    }

    /**
     * 减库存,减去某本书的库存
     * @param id
     */
    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);
    }
}

测试类

// 把xml配置的方式准备对象的过程画一个流程图出来
public class TxTest {
    public static void main(String[] args) throws SQLException {
        System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY,"d:\\code");
        ApplicationContext context = new ClassPathXmlApplicationContext("tx.xml");
        BookService bookService = context.getBean("bookService", BookService.class);
        bookService.checkout("zhangsan",1);
    }
}

从加载配置开始看,点进parse方法查看如何加载解析配置

点进看看默认的命名空间

点进去

 看一下BEANS_NAMESPACE_URI对应的值,可以看到默认的命名空间对应的是bean的命名空间

点进parseCustomElement

 点进去

 点进去

点进去

 点进去

点进去

 点进去

返回

解析pointcut

点进parsePointcut 

 点进createPointcutDefinition

 解析advisor

 点进parseAdvisor

点进 createAdvisorBeanDefinition

 解析tx标签

 点进去

点进去

 点进去

 点进去

点进去

 点进doParse

 点进去

对应到配置中 

 然后就是不断的返回,到此xml配置文件的解析完成。

 总结一下上面的解析过程,

解析tx元素的时候创建NameMatchTransactionAttributeSource

解析pointcut创建AspectJExpressionPointcut元素的时候

解析advisor元素的时候创建DefaultBeanFactoryPointcutAdvisor

还有一个对象AspectJAwareAdvisorAutoProxyCreator还没创建。如下图

invokeBeanFactoryPostProcessors(beanFactory);

BeanFactoryPostProcessor的一个子类PropertySourcesPlaceholderConfigurer在这里可以执行,完成对占位符的替换

registerBeanPostProcessors(beanFactory);

由图可以看到AbstractAdvisorAutoProxyCreator是BeanPostProcessor的一个子类,所以在AbstractAdvisorAutoProxyCreator应该在这一步被注册进去

执行之前

 走完这一步

可以看到多了一个AspectJAwareAdvisorAutoProxyCreator对象,说明这个对象在这一步中被创建 

继续走到下面的finishBeanFactoryInitialization(beanFactory);

点进去getBean-->doGetBean-->getSingleton-->createBean。对上述这些对象进行创建获取。在resolveBeforeInstantiation方法中

点进去 

遍历的四个BeanPostProcessor对象 

 点进去

 点进去

点进去

点进去

 点进去

 返回的matchFound如果为true,则加入结果

到此将advisor类型的beanName加入到result集合中。

往回走,走到

 点进去,创建advisor类型的DefaultBeanFactoryPointcutAdvisor对象,走创建对象的流程

 执行populate方法

点进去

 这个方法还没贴完

  这个方法还没贴完

 到这处理一个参数的流程走完,下面看一下里面有些方法具体的流程

这里处理一下参数的值(myAdvice参数的值)

 将处理好的参数转换成这个参数对应的类型

 点进去

 点进去

 点进去

 点进去

 txPoint参数

 点进去

走创建对象的流程,因为txPoint是原型的,所以这里进到

点进去,查看是否在创建对象之前做什么操作

 可以看到没有做什么其他操作,继续往下走,走到doCreateBean-->createBeanInstance选择对应构造器进行创建对象

到此resolveReference

 走完下面的步骤,到此populateBean方法走完,看一下当前对象的值的情况

 继续往下走initializeBean方法

 这个时候这个DefaultBeanFactoryPointcutAdvisor已经创建完成,但是这个对象中的advice参数并没有值。

继续往回走,这个这个advisor创建完成并添加进集合中了。 

执行完返回

 点进去

 返回

 返回resolveBeforeInstantiation方法执行完了

dataSource对象创建就不具体看了,这里看一下赋值populateBean方法

 进入initialzation方法

点进AfterBeanPostProcessor方法看看有没有生成代理对象

 点进去

点进去

可以看到没有获取到当前对象的advice和advisor,所以不需要对当前对象进行代理操作。到此dataSource对象就创建完成了。接着回到for循环接着创建其他对象

 其他对象就不看了看一下bookService,因为bookService中要注入bookDao,我们看一下对于要注入的bookDao是怎么处理的

 点进去

点进去

 在applyPropertyValues方法中

 点进去

 点进去

获取该对象

 jdbcTemplate注入到bookDao中创建对象,在bookDao对象创建好之后

 点进去 

点进去

 点进去

点进去

 点进去

点进去

看一下第一个判断条件 

 执行第二个判断条件

因为adviceBeanName是myAdvice,这里getBean就是获取一个beanName=myAdvice,Class=Advice的对象,接下来就是创建myAdvice对象流程 

创建对象部分不看,直接看populateBean部分

 点进去

另一个参数

 点进去

 进行创建和属性注入,这里不做详细阐述。直接看到myAdvice对象创建完成。

 这时候可以看到myAdvice对象是TransactionInterceptor类型的。我们来看一下这个类与advice之间的关系

 所以以后可以直接用子类实现Interceptor来实现advice

 

返回

 返回 

 返回 

 返回

 返回

创建代理的bookDao后返回注入bookService.

 然后bookService同样需要在对象创建完成之后进行代理

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值