Spring框架学习(三)
自动注入
- 使用场景:
在spring配置文件中对象名和ref=“id”id名相同使用自动注入,可以不配置<property/>
- 两种配置方式:
1.在<bean>
中通过autowire=“”配置,只对该<bean>
生效。
2.在<beans>
中通过default-autowire=“”配置,表示当前文件中所有<bean>
都是全局配置内容。 - autowire=“”可取值
1.default:默认值,格局全局default-autowire=“”值,默认全局和局部都没有配置情况下,相当于no。
2.no:不自动注入
3.byName:通过名称自动注入,在Spring容器中找类的id。
4.byType:根据类型注入,spring容器中不可以出现两个相同的类型的<bean>
。
5.constructor:根据构造方法注入,提供对应的构造方法,底层使用byName,构造方法参数名和其他<bean>
的id相同。
Spring中加载properties文件
- 在src下新建properties文件
- 在spring配置文件中先引入xmls:context,在下面添加,如果需要记载多个配置文件逗号分割:
<context:property-placeholder location="classpath:db.properties"/>
添加属性文件记载,并且在<bean>
中开启自动注入。
注意:sqlSessionFactoryBean的id不能叫sqlSessionFactory。将原来通过ref引用替换为value赋值,自动注入只能影响ref,不会影响value赋值。
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.bjsxt.mapper"></property>
<property name="sqlSessionFactoryBeanName" value="factory"></property>
</bean>
- 在被Spring管理的类中通过@value("${key}")取出properties中内容。
1.添加注解扫描:
<context:component-scan base-package="com.bjsxt.service.impl">
</context:compo nent-scan>
2.在类中添加,key和变量名可以不相同。变量类型任意,只要保证key对应的value能转换成这个类型就可以。
@Value("${my.demo}")
private String test;
scope属性
- 概念:
bean中的属性,作用是控制对象有效范围(单例,多例)。<bean/>
标签对应的对象默认是单例的,无论获取多少次都是同一个对象。 - scope可取值:
1.singleton为默认值,单例
2.prototype为多例,每次获取重新实例化
3.request为每次请求重新实例化
4.session为每个会话对象内,对象时单例的。
5.application在application对象内是单例的
6.global session spring推出一个对象依赖于spring-webmvc-portlet,类似session。
单例设计模式
作用:在应用程序有保证最多只能有一个实例。
好处:提升运行效率,实现数据共享
- 懒汉式:
对象只有在被调用的时候才去创建:
package test;
//单例模式-懒汉式
public class SingleTon {
private static SingleTon singleton;
//实例方法,实例方法必须通过对象调用,设置方法为静态方法 *
private SingleTon(){};
//由于对象需要被静态方法调用,把方法设置为 static
//由于对象是 static,必须要设置访问权限修饰符为 private , 如果是 public 可以直接调用对象,不执行访问入口
private static SingleTon sg(){
if(singleton==null){
synchronized(SingleTon.class){//多线程访问下,可能出现 if 同时成立的情况,添加锁
if(singleton==null){
singleton=new SingleTon();
}
}
}
return singleton;
}
public static void main(String[] args) {
SingleTon sg1=new SingleTon().sg();
SingleTon sg2=new SingleTon().sg();
System.out.print(sg1==sg2);
}
}
由于添加锁,导致运行效率降低。
- 饿汉式:
解决了懒汉式中多线程访问可能出现的同一个对象和效率低的问题。
package test;
public class SingleTon2 {
private static SingleTon2 singleton=new SingleTon2();//直接在开始创建实例对象
private SingleTon2(){};
private static SingleTon2 gs(){
return singleton;
}
public static void main(String[] args) {
SingleTon2 sg1=new SingleTon2().gs();
SingleTon2 sg2=new SingleTon2().gs();
System.out.print(sg1==sg2);
}
}
声明式事务
编程式事务:由程序员编程事务控制代码,OpenSessionInView编程式事务。
声明式事务:事务控制代码已经由spring写好,程序员只需要声明哪些方法需要进行事务控制和如何进行事务控制。声明式事务都是针对于ServiceImpl类下方法的。事务管理器基于通知(advice)的。
在spring配置文件中配置声明式事务:
<context:property-placeholder location="classpath:db.properties,classpath:second.pr operties"/>
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverMa nagerDataSource">
<property name="driverClassName" value="${jdbc.driver}"></property>
<property name="url" value="${jdbc.url}"></property>
<property name="username" value="${jdbc.username}"></property>
<property name="password" value="${jdbc.password}"></property>
</bean>
<!-- spring-jdbc.jar 中 -->
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSour ceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- 配置声明式事务 -->
<tx:advice id="txAdvice" transaction-manager="txManager">
<tx:attributes>
<!-- 哪些方法需要有事务控制 -->
<!-- 方法以 ins 开头事务管理 -->
<tx:method name="ins*" />
<tx:method name="del*" />
<tx:method name="upd*" />
<tx:method name="*" />
</tx:attributes>
</tx:advice>
<aop:config>
<!-- 切点范围设置大一些 -->
<aop:pointcut expression="execution(* com.bjsxt.service.impl.*.*(..))" id="mypoint" />
<aop:advisor advice-ref="txAdvice" pointcut-ref="mypoint" />
</aop:config>
声明式事务中属性解释
1.name=“”哪些方法需要有事务控制:支持*通配符。
2.readonly=“boolean”是否 是只读事务。如果为true,则通知数据库此事务为只读事务,数据化优化,会对性能有一定提升,因此只要是查询的方法则使用此数据。如果为false,事务需要提交的事务,建议新增,删除,修改。
3.propagation控制事务传播行为:
当一个具有事务控制的方法被另一个有事务控制的方法调用后,需要如何管理事务。REQUIRED(默认值):如果当前有事务,则在事务中执行,如果当前没有事务新建一个事务。
SUPPORTS:如果当前有事务则在事务中执行,如果当前没有事务则在非事务状态下执行。
MANDATORY:必须在事务内部执行,如果当前有事务,就在事务中执行,如果没有事务,报错。
REQURES_NEW:必须在事务中执行,如果当前没有事务,新建事务,如果当前有事务,将当前事务挂起,重新创建事务。
NOT_SUPPORTED:必须在非事务下执行,如果当前没有事务正常执行如果当前有事务,将当前事务挂起。
NEVER:必须在非事务状态下执行,如果当前没有事务,正常执行,如果当前有事务,报错。
NESTED:必须在事务状态下执行,如果没有事务,新建事务,如果当前有事务,创建一个嵌套事务。
4. isolation=“”事务隔离级别
在多线程或并发访问下如何保证访问到的数据具有完整性的。
脏读:
事务A读取到另一个事务B中未提交的数据,另一个事务中可能进行了改变,此时A事务读取的数据可能和数据库中的数据不一致,此时认为数据是脏数据,读脏数据过程叫脏读。
不可重复读:
主要针对的是某行数据,操作是修改操作,两次读取在同一个事务中。当事务A第一次读取事务后,事务B对事务A读取的数据进行修改,事务A中再次读取的数据和之前读取的 数据不一致,过程不可重复读。
幻读:
主要针对的操作是新增或删除。两次事务的结果。事务A按照特定条件插叙出结果,事务B新增一条符合条件的数据事务A中查询的数据和数据库中的数据不一致,称为幻读。
DEFAULT:默认值,由底层数据库自动判断应该使用什么隔离界别。
READ_UNCOMMITTED:可以读取未提交数据,可能出现脏读,不重复读,幻读。效率最高。
READ_COMITTED:只能读取其他事务已提交的数据,可以防止脏读,可能出现不重复读和幻读。
REPEATABLE_READ:读取的数据被添加锁,防止其他事务修改此数据,可以防止不可重复读,可能出现幻读。
SERIALIZABLE:排队操作,对整体表添加锁,一个事务在操作数据时,另一个事务等待事务操作完成后才能操作该表。最安全但是效率最低。
5. rollback-for=“异常类型全限定路径”
当出现什么异常时需要进行回滚,手动抛出异常一定给该属性值。
no-rollback-for="”,当出现什么异常时不滚回事务。
Spring中常用注解
1.@Component 创建类对象,相当于配置<bean/>
2.@Service 与@Component 功能相同.写在ServiceImpl类上。
3.@Repository 与@Component 功能相同,写在数据访问层类上。
4.@Controller 与@Component 功能相同,写在控制器类上。
5.@Resource(不需要写对象的 get/set),java 中的注解,默认按照 byName 注入,如果没有名称对象,按照 byType 注入。建议将对象名称和Spring容器中的对象名相同。
6.@Autowired(不需要写对象的 get/set),spring 的注解,默认按照byType注入。
7.@Value() 获取 properties 文件中内容
8.@Pointcut() 定义切点
9.@Aspect() 定义切面类
10.@Before() 前置通知
11.@After 后置通知
12.@AfterReturning 后置通知,必须切点正确执行
13.@AfterThrowing 异常通知
14.@Arround 环绕通知