【十五】Spring

目录

一、IOC与DI

二、AOP

AspectJ的AOP与Spring的区别

三、事务的传播行为

四、Spring 声明式事务和编程式事务

五、@Autowire和@Resource的区别


一、IOC与DI

IOC和DI是一个概念,依赖注入,即当某个角色需要另外一个角色协助的时候,在传统的程序设计过程中,通常由调用者来创建被调用者的实例。但在spring中,创建被调用者的工作不再由调用者来完成,创建(在spring容器启动的时候,spring会把你在配置文件中配置的bean都初始化好,然后在你需要调用的时候,就把它已经初始化好的那些bean分配给你需要调用这些bean的类)被调用者的工作由spring来完成,然后注入调用者,因此称为控制反转。

spring以动态灵活的方式来管理对象 , 注入的三种方式,构造方法注入、setter注入、基于注解的注入。

构造注入的优点:可以在构造器中决定依赖关系的顺序。

设置注入的优点:直观,自然

spring提供了许多IOC容器的实现,比如XmlBeanFactory,ClasspathXmlApplicationContext,其中XmlBeanFactory就是针对最基本的ioc容器的实现,这个IOC容器可以读取XML文件定义的BeanDefinition(XML文件中对bean的描述)

IOC容器的初始化包括BeanDefinition的Resource定位、载入和注册这三个基本的过程。

二、AOP

AOP可以说是对OOP的补充和完善。OOP引入封装、继承和多态性等概念来建立一种对象层次结构,用以模拟公共行为的一个集合。当我们需要为分散的对象引入公共行为的时候,OOP则显得无能为力。也就是说,OOP允许你定义从上到下的关系,但并不适合定义从左到右的关系。例如日志功能。日志代码往往水平地散布在所有对象层次中,而与它所散布到的对象的核心功能毫无关系。在OOP设计中,它导致了大量代码的重复,而不利于各个模块的重用。(将相同逻辑的重复代码横向抽取出来,使用动态代理技术将这些重复代码织入到目标对象方法中,实现和原来一样的功能。这样一来,我们就在写业务时只关心业务代码,而不用关心与业务无关的代码)

Spring AOP默认是使用JDK动态代理,如果代理的类没有接口则会使用CGLib代理

如果是单例的我们最好使用CGLib代理,如果是多例的我们最好使用JDK代理。

原因:JDK在创建代理对象时的性能要高于CGLib代理,而生成代理对象的运行性能却比CGLib的低。

①spring aop xml方式。

    <aop:config>

        <aop:pointcut expression="execution(*  com.aop.impl.xml.ArithmeticCalculator.*(..))"  id="pointcut"/>

        <aop:aspect ref="logging" order="1">

            <aop:before method="beforeMethod"  pointcut-ref="pointcut"/>

            <aop:after method="afterMethod"  pointcut-ref="pointcut"/>

            <aop:after-returning  method="afterReturnning" returning="result"  pointcut-ref="pointcut"/>

            <aop:after-throwing  method="afterThrowing" throwing="ex"  pointcut-ref="pointcut"/>

             <!-- <aop:around  method="aroundMethod" pointcut-ref="pointcut"/>  -->

        </aop:aspect>

        <aop:aspect ref="validation" order="2">

            <aop:before method="validation"  pointcut-ref="pointcut"/>

        </aop:aspect>

    </aop:config>

②spring aop 注解方式。

AspectJ的AOP与Spring的区别

AspectJ在编译时就增强了目标对象(在编译阶段将Aspect织入Java字节码中, 运行的时候就是经过增强之后的AOP对象),Spring AOP的动态代理则是在每次运行时动态的增强,生成AOP代理对象,区别在于生成AOP代理对象的时机不同,相对来说AspectJ的静态代理方式具有更好的性能,但是AspectJ需要特定的编译器进行处理,而Spring AOP则无需特定的编译器处理。

三、事务的传播行为

ServiceA{

    methodA(){

        for(int i=0;i<=1i++){

            serviceB.methodB();

        }

    }

}

ServiceB(){

    @Transcational

    methodB(){

    

    }

}

methodB的事务隔离级别

ServiceA的methodA()中存在事务

ServiceA的methodA()中没有事务

描述

Propagation.REQUIRED

在methodA的事务中运行

给methodA启动一个新的事务,但是在methodB的事务中运行如果调用方有事务在运行,那么当前方法就在这个事务中运行,否则就为调用方重新启动一个新的事务,并且在被调用方法的事务中运行。

Propagation.REQUIRES_NEW

为methodA开启一个新的事务,但是在methodB的事务中运行

为methodA开启一个新的事务,但是在methodB的事务中运行

无论如何为调用方开启一个新的事务, 但是在被调用方的事务内运行. 如果当前有事务在运行, 就应该先挂起它.

Propagation.SUPPORTS

在methodA的事务中运行

在methodB的事务中运行

如果调用方有事务在运行,当前的方法就在这个事务内运行,否则他可以不运行在调用者的事务中(在被调用方的事务内运行)

Propagation.REQUIRED:

 

Propagation.REQUIRES_NEW:

四、Spring 声明式事务和编程式事务

1、编程式事务使用TransactionTemplate或者直接使用底层的PlatformTransactionManager,需要手动开启事务和提交事务。对于编程式事务管理,spring推荐使用TransactionTemplate。

2、声明式事务是建立在AOP之上的。其本质是对方法前后进行拦截,然后在目标方法开始之前创建或者加入一个事务,在执行完目标方法之后根据执行情况提交或者回滚事务。声明式事务最大的优点就是不需要通过编程的方式管理事务,这样就不需要在业务逻辑代码中掺杂事务管理的代码,只需在配置文件中做相关的事务规则声明(或通过基于@Transactional注解的方式),便可以将事务规则应用到业务逻辑中。两种方式:

①基于tx和aop名字空间的xml配置文件    

    <!-- 配置事务属性 -->

    <tx:advice id="txAdvice"  transaction-manager="transactionManager">

        <tx:attributes>

            <tx:method name="purchase"  propagation="REQUIRES_NEW"/><!-- 指定重开事务的方法 -->

            <tx:method name="*"/>

        </tx:attributes>

    </tx:advice>

    <!-- 配置事务切入点,以及把事务切入点和事务属性关联起来 -->

    <aop:config>

        <aop:pointcut expression="execution(*  tx.xml.service.*.*(..))" id="txPointCut"/>

        <aop:advisor advice-ref="txAdvice"  pointcut-ref="txPointCut"/>

    </aop:config>

②使用@Transactional注解    

    <!-- 配置事务管理器 -->

    <bean id="transactionManager"

    class="org.springframework.jdbc.datasource.DataSourceTransactionManager">

        <property name="dataSource"  ref="dataSource"></property>

    </bean>

    <!-- 启动事务注解 -->

    <tx:annotation-driven  transaction-manager="transactionManager"/>

五、@Autowire和@Resource的区别

@Autowire bytype进行匹配,如果有多个匹配的类型,使用@Qualifiter 指定注入 Bean 的名称(不指定会报错)

@Resource名称可以通过name属性进行指定,如果没有指定name属性,当注解写在字段上时,默认取字段名,按照名称查找,如果注解写在setter方法上默认取属性名进行装配。当找不到与名称匹配的bean时才按照类型进行装配。但是需要注意的是,如果name属性一旦指定,就只会按照名称进行装配。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值