spring的一些思考

开源框架

Spring

核心组件
- Bean:包装对象,使得对象之间的依赖关系可以被IOC容器管理。
- core(深似Util) : 有很多关键类,一个重要的组成部分把所有资源都抽象成了一个接口。
- Context:,发现每个bean之间的关系,保存对象之间的依赖状态

Spring IOC

  • 它是什么?
  • 它能解决什么?
  • 它适合什么场景不适合什么场景

控制反转,就是把程序代码直接操控的对象的调用权交给容器,由容器来实现对象组件的装配与管理。我的理解是,其本质是对象间依赖关系的一种管理。
它解决了在一些系统间因为强耦合造成的系统冗杂,不易修改的问题

  • DI机制是什么?
    宽泛点来说我们可以把DI看做IOC的一种实现手段,组件本身不负责擦找资源或者其他依赖的协作对象,而只负责配置对象,因此,查找资源的逻辑应该从组件中抽取出来,由IOC容器管理。

Spring bean

Bean的注入

构造器注入:通常使用构造器注入来注入必要的依赖关系,但是有时候一个对象的构造器可以有点多,因此也会用setter
setter注入,一般用来注入可选的依赖关系
注解注入
- @Autowired
- @Qualifier
- @Resource

扫描注入:
1. context命名空间:配置schema
2. context:component-scan标签

Bean的作用域
  • Singleton:将统一共享实例注入到每一个协作对象
  • prototype:对于不能共享的对象实例,为其分配一个对应的对象实例,比如,每个客户信息的对象
  • request
  • session
  • global session
    后三个只能在Web应
    用中使用。也就是说,只有在支持Web应用的ApplicationContext中使用这三个scope才是合理的
bean的生命周期
自动转配模式的区别
  • no
  • byName
  • byType
  • constructor
  • autodetect:该模式自动探测使用构造器自动装配或者byType自动装配。首先,首先会尝试找合适的带参数的构造器,如果找到的话就是用构造器自动装配,如果在bean内部没有找到相应的构造器或者是无参构造器,容器就会自动选择byTpe的自动装配方式
@Required注解

在产品级别的应用中,IoC容器可能声明了数十万了bean,bean与bean之间有着复杂的依赖关系。设值注解方法的短板之一就是验证所有的属性是否被注解是一项十分困难的操作。可以通过在中设置“dependency-check”来解决这个问题。
RequiredAnnotationBeanPostProcessor是Spring中的后置处理用来验证被@Required 注解的bean属性是否被正确的设置了。

在应用程序的生命周期中,你可能不大愿意花时间在验证所有bean的属性是否按照上下文文件正确配置。或者你宁可验证某个bean的特定属性是否被正确的设置。即使是用“dependency-check”属性也不能很好的解决这个问题,在这种情况下,你需要使用@Required 注解。

Spring的AOP

采用动态代理机制和字节码生成技术实现,动态代理机制和字节码生成都是在运行期间为目标对象生成一个代理对象。

从动态代理机制的根源说起:
这里写图片描述

JDK1.3之后引入的动态代理:
一个代理类:java.reflect.Proxy
一个代理接口:java.lang.reflect.InvocationHandler
InvocationHandler是实现横切逻辑的地方,作用与Advice是一样的,可以在这个基础上细化程序结构,根据Advice的类型,分化出对应不同Advice的横切逻辑。

缺点:只能适用于有接口的目标类
在没有接口的目标类,使用CGLIB库生成的目标对象对象的子类,这是一个动态字节码生成库。

CLIB内部存在针对requestable所提供的callback,使得其可以对request()方法请求进行访问控制,通过CLIB的Enhancer为目标对象动态生成一个子类,将访问控制的逻辑加入到该子类中。
CLIB 无法对final方法进行覆写。

一些基本概念
  • Aspect :切面
  • Joinpoint:程序执行过程中明确的点,如方法的调用或特定的异常被抛出。
  • pointcut:切入点,指定一个通知将被引发的一系列连接点的集合。AOP框架必须允许开发者指定切入点,例如,使用正则表达式。
  • Advice:参照pointcut拦截到Joinpoint方法之后要做的事就是通知。
  • Target:代理的目标对象
  • Weaving:把切面应用到目标对象来创建新的代理对象的过程。
五种类型支持
  • Before advice : <aop:before>
  • After advice : <aop:after>
  • After returnadvice : <aop:after-returning>
  • Around advice : <aop:around>
  • Afterthrowing advice : aop:after-throwing

实现方式
  • xml

在Spring配置中声明切面

<!--声明切面-->
    <bean id="userManager" class="com.tgb.aop.UserManagerImpl"/>  

    <!--<bean id="aspcejHandler" class="com.tgb.aop.AspceJAdvice"/>-->  
    <bean id="xmlHandler" class="com.tgb.aop.XMLAdvice" />  
    <aop:config>  
        <aop:aspect id="aspect" ref="xmlHandler">  
            <aop:pointcut id="pointUserMgr" expression="execution(* com.tgb.aop.*.find*(..))"/>  

            <aop:before method="doBefore"  pointcut-ref="pointUserMgr"/>  
            <aop:after method="doAfter"  pointcut-ref="pointUserMgr"/>  
            <aop:around method="doAround"  pointcut-ref="pointUserMgr"/>  
            <aop:after-returning method="doReturn"  pointcut-ref="pointUserMgr"/>  
            <aop:after-throwing method="doThrowing" throwing="ex" pointcut-ref="pointUserMgr"/>  

        </aop:aspect>  
    </aop:config>  
</beans>  
  • 基于@Aspect注解驱动的切面

这里写图片描述
- 纯pojo

应用案例:
  • 异常处理
    unchecked exception通常额可以做的是就是记录日志,通知相应人员。我们应该让他们散落在系统各处嘛?这样不好,以为内我们可以将其归并在一处进行处理。对于系统中的这些异常,就是一种cross-cutting concern。
  • 安全检查
  • 缓存:让缓存的实现独立于业务对象的实现。

JDBC API

JDBC的烦恼:

  • 繁琐
  • SQLExceptio没有将具体的异常子类化,以进一步抽象不同的数据访问异常情况。而是以为ErrorCode的方式区分数据访问过程中出现的不同情况
  • 可能出现因为异常资源不能关闭的情况

抓住JdbcTemplate,就是抓住了JDBC API的核心

  • JdbcTrmplate是整个Spring数据访问的Helper类(Spring扩展),我们也可以自己实现Helper类.
  • 封装所有基于JDBC的数据访问代码
  • 对SQLException所提供的异常信息在框架内进行统一转译。委托的具体的SQLExceptionTranslator实现类来进行SQLException的转译。
  • JDB通过模板方式对基于JDBC的数据访问代码进行统一的封装,引入相应的callback接口定义,以免该每次使用Helper类都需要子类化。

从另一个层面:
- jdbcTemplate完成了资源的创建和释放的工作
- 完成了JDBC核心流程的工作
- 仅仅需要传递DataSource就可以把他实例话
- 只需要创建一次
- 线程安全

模板方法模式

模板方法模式就是对算法和行为逻辑的一种封装。将确定的行为以模板的形式定义,而将不同的行为留给相应的子类实现。

Spring的DataSource

DataSource的基本角色是ConnectionFactory,所有的数据库链接将通过DataSource接口统一管理
- 拥有缓冲池
- 分布式事务(一般不用)
- 本地访问:classpath
- 远程访问:JNDI

JdbcDaoSupport

  • 将DataSource和JdbcTemplate全部提取到统一的超类中。

使用JDBCTemplate

在Dao类中,用JdbcTemple,作为属性,spring对其进行注入,在xml中注入DataSource

Spring访问数据:Spring对各种ORM的集成

  • 统一的资源管理
  • 特定于ORM的数据访问异常到Spring异常体系转译
  • 统一的数据访问以及控制方式
    事务管理抽象层:接管各种数据访问方式的特定事务管理,下面我们就会讲是spring的事务管理

这里写图片描述

有没有觉得,spring的数据访问格式是对面向对象的一种出神入化的利用?在以后自己造轮子的时候,应该多多学习这种。

spring的事务

事务是什么? ——ACID

  • 原子性:事务的提交每部一起放弃,要么一起成功
  • 一致性:数据资源在事务执行之前处于某个数据一致性状态,在事务执行之后也要保持一致性状态
  • 隔离性:兼顾影响事务的一致性,当两个事务或者更多事务同事访问同一个数据资源的时候,不同的隔离级别就决定了各个事务对该资源访问的不同行为
  • 持久性:一旦提交成功,变更不可逆转

事务的回滚

Spring默认情况喜爱对RunTimeException进行事务回滚,这个是unchecked Exception。
如何改变默认规则:

  • 让cheacked Exception也回滚:@Transactional(rollbackFor=Exception.class)
  • 让unchecked Exception 不回滚 @Transactional(notRollbackFor=RunTimeException.class)
  • 不需要事务管理的方法:@Transactional(propagation=Propagation.NOT_SUPPORTED)
  • 还可以设置为只读:@Transactional(propagation=Propagation.NOT_SUPPORTED,readOnly=true),
传播行为意义
REQUIRED业务方法要在一个事务中运行
NOT_REQUIRED不需要事务
MANDATORY 委托一个事务,不能自己有事务
SUPPORT被某个事务范围内被调用就融入
NEVER绝对不允许有事务
NESTED内部事务的回滚不会对外部事务造成影响

不讨喜的

  1. Dirty reads–读脏数据。也就是说,比如事务A的未提交(还依然缓存)的数据被事务B读走,如果事务A失败回滚,会导致事务B所读取的的数据是错误的。
    2: non-repeatable reads–数据不可重复读。比如事务A中两处读取数据-total-的值。在第一读的时候,total是100,然后事务B就把total的数据改成 200,事务A再读一次,结果就发现,total竟然就变成200了,造成事务A数据混乱。
    3: phantom reads–幻象读数据,事务在插入事先检测不存在的记录时,惊奇的发现这些数据已经存在了,之前的检测读获取到的数据如同鬼影一般。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值