一、自动注入
1)在 Spring 配置文件中一个<property>的name 与 ref要引用的<bean>的id相同时,可以使用自动注入,不必配置<property/>
2)配置方式
1.在<bean/>中通过autowire=" "配置,则只对这个bean生效。
2.在<beans>中通过 default-autowire=" "来配置,表明当前xml配置文件中所有的<bean>都是使用自动注入
3)autowire的取值
1.default:默认值,根据全局的default-autowire的值来确定,当全局和局部都没有配置的时候,相当于no
2.no:不自动注入
3.byName:通过名称自动注入,在Spring容器中寻找与name相同的那个id所对应的<bean/>去注入
4.byType:根据class类型进行自动注入,Spring容器中不可以出现两个相同类型的<bean>
5.constructor:根据构造方法注入,所以应该提供对应参数的构造方法(构造方法参数中包含注入对象),底层实际上也是利用byName,构造方法参数名和其他<bean>的id相同。
二、Spring中加载properties文件
1)首先在src下新建一个properties配置文件
2)在Spring的配置文件中先引入xmlns:context,在下面添加properties配置文件的路径
如果需要记载多个配置文件逗号分割
<context:property-placeholder location="classpath:db.properties"/>
3)当添加了属性文件加载后,如果在beans中开启了自动注入,则需要注意:
1.SqlSessionFactory 的bean的id不能叫做sqlSessionFactory,原因在于如果在这里使用了自动注入功能,则会因为自动注入优先级太高导致属性文件不能在加载对象之前而加载,导致dataSource无法在properties文件中取值。
2.可以改为
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.bjsxt.mapper"></property>
<property name="sqlSessionFactoryBeanName" value="factory"></property>
在MapperScannerConfigurer类中,有一个sqlSessionFactoryBeanName的成员变量,是String类型,所以可以使用value赋值
4)在被Spring管理的类中通过@Value(“${key}”)取出properties中内容,或在xml文件中通过${key}来取值
1.在类中如果使用@Value注解的话,需要在xml配置文件中添加注解扫描
<context:component-scan base-package="com.bjsxt.service.impl"></context:component-scan>
2.在类中通过在属性上方加@Value注解来进行取值
@Value("${my.demo}")
private String test;
三、bean的scope属性
作用:控制对象的有效范围(单例、多例)
<bean/>标签对应的对象默认是单例的,也就是说在xml文件被加载的时候就将对象创建出来,且只会创建这一个对象。
1)scope 可取值
1 singleton 默认值,单例
2 prototype 多例,每次获取重新实例化
3 request 每次请求重新实例化
4 session 每个会话对象内,对象是单例的
5 application 在 application 对象内是单例
6 global session spring 推 出 的 一 个 对 象 , 依 赖 于 spring-webmvc-portlet ,类似于 session
2)关于单例设计模式
见本篇博文
四、声明式事务
1)首先区分编程式事务与声明式事务的区别
编程式事务:由程序员编程事务,控制代码,例如OpenSessionInView的编写,就是一个编程事务(手动进行commit或者rollback)
声明式事务:事务控制代码已经由Spring封装好,只需要在配置文件中声明出哪些方法需要进行事务控制和 如何进行事务控制即可。
2)声明式事务都是针对于ServiceImpl类下的方法的
事务管理器是基于通知(advice)的
3)在Spring中配置声明式事务
<?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:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd"
default-autowire="byName">
<context:property-placeholder location="classpath:db.properties,classpath:second.properties"/>
<context:component-scan base-package="com.bjsxt.service.impl"></context:component-scan>
<!-- 数据源 -->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<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>
<!-- SqlSessinFactory对象 -->
<bean id="factory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="typeAliasesPackage" value="com.bjsxt.pojo"></property>
</bean>
<!-- 扫描器 -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.bjsxt.mapper"></property>
<property name="sqlSessionFactoryBeanName" value="factory"></property>
</bean>
<!-- 注入 -->
<!-- <bean id="usersService" class="com.bjsxt.service.impl.UsersServiceImpl">
<property name=""></property>
</bean> -->
<bean id="txManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<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="*" read-only="true"/>
</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>
</beans>
4)tx:method 标签的属性值
1.name=" " 其中写方法名,表明此方法需要有事务控制(支持*通配符)
2.readonly="boolean" 是否为只读事务
如果为 true,告诉数据库此事务为只读事务.数据化优化,会对性能有一定提升,所以只要是查询的方法,建议使用此数据.
如果为 false(默认值),事务需要提交的事务.建议新增,删除,修改
3.propagation 控制事务传播行为
当一个具有事务控制的方法被另一个有事务控制的方法调用后,需要如何管理事务(新建事务?在事务中执行?把事务挂起?报异常?)
REQUIRED (默认值): 如果当前有事务,就在事务中执行,如果当前没有事务,新建一个事务.
SUPPORTS:如果当前有事务就在事务中执行,如果当前没有事务,就在非事务状态下执行.
REQUIRES_NEW:必须在事务中执行,如果当前没有事务,新建事务,如果当前有事务,把当前事务挂起
NOT_SUPPORTED:必须在非事务下执行,如果当前没有事务,正常执行,如果当前有事务,把当前事务挂起.
NEVER:必须在非事务状态下执行,如果当前没有事务,正常执行, 如果当前有事务,报错
NESTED:必须在事务状态下执行.如果没有事务,新建事务,如果当前有事务,创建一个嵌套事务
4.isolation="" 事务隔离级别
在多线程或并发访问下如何保证访问到的数据具有完整性的.
有可能会出现脏读、不可重复读、幻读的数据完整性问题
脏读:一个事务(A)读取到另一个事务(B)中未提交的数据,另一个事务中数据可能进行了改变,此时 A事务读取的数据可能和数据库中数据是不一致的,此时认为数据是脏数据,读取脏数据过程叫做脏读
不可重复读:主要针对的是某行数据.(或行中某列),主要针对于修改操作,并且出现在两次读取在同一个事务中的时候。当事务 A 第一次读取事务后,事务 B 对事务 A 读取的数据进行修改,事务 A 中再次读取的数据和之前读取的数据不一致,为不可重复读
解决此问题需要数据库对某行数据加锁
幻读:主要针对的操作是新增或删除,并且为两次事务的结果。事务A按照特定条件查询出结果,事务B新增或删除了一条符合事务A查询条件的数据,导致事务A中查询的数据和数据库中的数据不一致,事务A仿佛出现了幻觉,为幻读。
解决此问题需要数据库对整个表加锁
DEFAULT: 默认值,由底层数据库自动判断应该使用什么隔离级别
READ_COMMITTED:只能读取其他事务已提交数据.可以防止脏读,可能出现不可重复读和幻读.(效率最高)
REPEATABLE_READ: 读取的数据被添加锁,防止其他事务修改此数据,可以防止不可重复读.脏读,可能出现幻读.
SERIALIZABLE: 排队操作,对整个表添加锁.一个事务在操作数据时,另一个事务等待事务操作完成后才能操作这个表(最安全,效率最低)
5.rollback-for="异常类型全限定路径"
当出现声明的异常的时候需要进行回滚,建议使用自己手动抛出的异常,手动抛异常一定要给该属性值
6.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 环绕通知