概念
依赖注入的方式
bean的自动注入
方式一:通过XML配置文件自动注入
<bean id="" class="" autowire="{byName,byType,constructor,default,no}"/>
方式二:通过注解的方式自动注入
代理模式
静态代理:
在代理类中包含一个目标类的对象引用,然后在使用时创建一个目标类对象并且创建一个代理类对象,并把目标类对象传给代理类对象,然后将它赋予代理类中的目标类对象引用,
然后代理类所代理的方法中通过其所包含的目标类对象引用调用目标类的方法,从而实现通过代理调用目标类方法的效果。
动态代理:
动态代理
有两种实现方式:
JDK的接口代理(常用)
public demo implements InvocationHandler{
//目标类
private Object target;
//获取代理类
public Object getProxy(){
return Proxy.newInstance(target.getClass().getClassLoader
,target.getClass().getInterface(),this);
}
//方法实行
public Object invoke(Object proxy,Method method,Object[] args){
return method.invoke(method,args);
}
}
Cglib代理(可以通过spring配置文件强制开启)
Cglib动态代理是利用asm开源包,对代理对象类的class文件加载进来,通过修改其字节码生成子类来处理
区别:
AOP(底层由动态代理实现)
四种类型:
实现方式一:advice类实现AOP四种接口
public void demo implements MethodBeforeAdvice{
public void before(Method method, Object[] objects, Object o) throws Throwable{
}
}
<aop:config>
<aop:pointcut id="" expression="execution()"/>
<aop:advisor-ref="" pointcut-ref=""/>
</aop:config>
实现方式二:切面类(aspect)实现advice方法
public void demo{
public void method1(){}
public void method2(){}
}
<aop:config>
<aop:aspect>
<aop:before method="method1" pointcut-ref=""/>
<aop:after method="method1" pointcut-ref=""/>
</aop:aspect>
</aop:config>
事务特性:ACID
事务类型
编程式事务
声明式事务(spring自带事务)
原理:通过AOP切面编程嵌入事务管理功能
propagation传播行为
REQUIRED(常用)
REQUIRED是常用的事务传播行为,如果当前没有事务,就新建一个事务,如果已经存在一个事务中,加入到这个事务中。
SUPPORTS
SUPPORTS表示当前方法不需要事务上下文,但是如果存在当前事务的话,那么这个方法会在这个事务中运行。
MANDATORY
MANDATORY表示该方法必须在事务中运行,如果当前事务不存在,则会抛出一个异常。不会主动开启一个事务。
REQUIRES_NEW
REQUIRES_NEW表示当前方法必须运行在它自己的事务中。一个新的事务将被启动,如果存在当前事务,在该方法执行期间,当前事务会被挂起(如果一个事务已经存在,则先将这个存在的事务挂起)。
NOT_SUPPORTED
NOT_SUPPORTED表示该方法不应该运行在事务中,如果存在当前事务,在该方法运行期间,当前事务将被挂起。
NEVER
NEVER表示当前方法不应该运行在事务上下文中,如果当前正有一个事务在运行,则会抛出异常。
NESTED
NESTED表示如果当前已经存在一个事务,那么该方法将会在嵌套事务中运行。嵌套的事务可以独立于当前事务进行单独地提交或回滚。如果当前事务不存在,那么其行为与REQUIRED一样。嵌套事务一个非常重要的概念就是内层事务依赖于外层事务。外层事务失败时,会回滚内层事务所做的动作。而内层事务操作失败并不会引起外层事务的回滚。
isolation事务隔离级别
出现的问题:
脏读(dirty read):当一个事务读取另一个事务尚未提交的修改时,产生脏读。
不可重复读(non-repeatable read):同一查询在同一事务中多次进行,由于其他提交事务所做的修改或删除,每次返回不同的结果集,此时发生非重复读。
幻像读(phantom read):同一查询在同一事务中多次进行,由于其他提交事务所做的插入操作,每次返回不同的结果集,此时发生幻像读。
spring给予问题的解决办法:
DEFAULT默认级别
DEFAULT为数据源(数据库)的默认隔离级别,以目前常用的MySQL为例,默认的隔离级别通常为REPEATABLE_READ。
READ_UNCOMMITTED未授权读取级别
这是最低的隔离级别,一个事务能读取到别的事务未提交的更新数据,很不安全,可能出现丢失更新、脏读、不可重复读、幻读。
READ_COMMITTED授权读取级别
以操作同一行数据为前提,读事务允许其他读事务和写事务,未提交的写事务禁止其他读事务和写事务。此隔离级别可以防止更新丢失、脏读,但不能防止不可重复读、幻读。此隔离级别可以通过“瞬间共享读锁”和“排他写锁”实现。
REPEATABLE_READ可重复读取级别
保证同一事务中先后执行的多次查询将返回同一结果,不受其他事务影响。以操作同一行数据为前提,读事务禁止其他写事务,但允许其他读事务,未提交的写事务禁止其他读事务和写事务。此隔离级别可以防止更新丢失、脏读、不可重复读,但不能防止幻读。
SERIALIZABLE序列化级别
所有的事务依次逐个执行,这样事务之间就完全不可能产生干扰。提供严格的事务隔离,此隔离级别可以防止更新丢失、脏读、不可重复读、幻读。如果仅仅通过“行级锁”是无法实现事务序列化的,必须通过其他机制保证新插入的数据不会被刚执行查询操作的事务访问到。
建议:
隔离级别越高,越能保证数据的完整性和一致性,但是对并发性能的影响也越大。对于多数应用程序,可以优先考虑把数据库系统的隔离级别设为Read Committed。它能够避免更新丢失、脏读,而且具有较好的并发性能。尽管它会导致不可重复读、幻读这些并发问题,在可能出现这类问题的个别场合,可以由应用程序采用悲观锁或乐观锁来控制。
read-only读写事务控制
代码配置
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="get*" read-only="true"/>
<tx:method name="find*" read-only="true"/>
<tx:method name="search*" read-only="true"/>
<tx:method name="*" propagation="REQUIRED" read-only="" isolation=""/>
</tx:attributes>
</tx:advice>
<aop:config>
<aop:pointcut id="txpc" expression="execution()"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="txpc"/>
</aop:config>
?
原文:https://www.cnblogs.com/MoonPiePlane/p/15054172.html