


![spring框架中的SET注入[4]




























Spring1
1. Spring框架的引言
spring
(春天),生于在2002年,由Rod Johnson
创作。Spring框架是一个集众多设计模式于一身的开源的
、轻量级
的项目管理
框架。致力于JAVAEE轻量级解决方案。相对于原来学过的框架而言,spring框架和之前学习的struts2 、 mybatis 框架有了本质的区别,不是替换原来的某个框架,而是对其进行整合管理
。
轻量级解决方案
:提供一个以简单的、统一的、高效的方式构造整个应用,并且可以将单层框架以最佳的组合揉和在一起建立一个连贯的体系。
2.Spring框架的核心作用
Spring 框架用来管理
[创建|使用|销毁]项目中的组件,由于spring 框架可以帮我们生产项目中组件对象,因此也习惯称spring是一个工厂|容器。
组件
: 项目中的service,dao,action,都是项目中的组件
注意
: spring框架通常不管理对实体类对象创建
3.第一个环境搭建
a. 引入依赖
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>4.3.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>4.3.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>4.3.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-expression</artifactId>
<version>4.3.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>4.3.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.3.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>4.3.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>4.3.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>4.3.2.RELEASE</version>
</dependency>
b. 引入配置文件
# 配置文件名称: 任意名称
# 配置文件位置: 项目中根下任意位置
# 配置文件的内容:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd ">
</beans>
c.创建组件


d.工厂管理
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--通过bean标签管理组件对象-->
<bean id="userDAO" class="com.baizhi.dao.UserDAOImpl"></bean>
</beans>

e.启动工厂
测试
public static void main(String[] args) {
//启动工厂
ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
//获取对象
UserDAO userDAO = (UserDAO) context.getBean("userDAO");
userDAO.save("小黑");
}
4.Spring框架中的核心思想
4.1 IOC[控制反转]
IOC(inversion of controll)控制反转
# 1.定义 将对象的创建由原来(new)的方式转移到配置文件中,交给spring工厂来创建对象
DI(dependcy Injection)依赖注入
# 1.定义 Spring不仅要创建对象,还要建立类与类之间的关系,因此在控制反转的基础上又提出了依赖注入的概念。
4.2 AOP[面向切面编程]
AOP( Aspect Oriental Programing ) 面向切面的编程
5. SET方式注入
5.1 八种基本类型+String类型 +日期类型的注入
<property name="name" value="zhagnsan"/>
<property name="age" value="21"/>
<property name="id" value="100063"/>
<property name="bir" value="2012/12/12"/>
<property name="price" value="23.23"/>

数组类型注入
<!--注入数组类型数据-->
<property name="qqs">
<array>
<value>xxx</value>
<value>qqq</value>
<value>vvvv</value>
</array>
</property>

注入引用类型和集合类型
<!--注入引用类型和对象-->
<property name="userDAO" ref="userDAO"/>
<property name="lists">
<list>
<value>aaa</value>
<value>bbb</value>
<value>ccc</value>
</list>
</property>
<property name="maps">
<map>
<entry key="aa" value="xiaohei"/>
<entry key="bb" value="xiaoming"/>
<entry key="cc" value="xiaosan"/>
</map>
</property>
<property name="props">
<props>
<prop key="url">jdbc:mysql://localhost:3306/test</prop>
<prop key="driver">com.mysql.jdbc.Driver</prop>
<prop key="username">hr</prop>
<prop key="password">hr</prop>
</props>
</property>

**注意**: 引用类型使用ref属性注入,基本类型使用value属性注入
6.构造注入
<constructor-arg index="0" name="id" value="1"/>
<constructor-arg index="1" name="name" value="xiaohei"/>
<constructor-arg index="2" name="age" value="12"/>
<constructor-arg index="3" name="qqs">
<array>
<value>xxx</value>
<value>222</value>
<value>333</value>
</array>
</constructor-arg>
注意:构造注入并不常用,不过在一些框架类中必须使用构造注入,这里先了解其注入语法即可。
7.自动注入
- autowire=”byName”
根据注入的属性名与配置文件中bean的id匹配,一致则注入,不一致报错
- autowire=”byType”
根据注入的属性类型,与配置文件中的类型匹配,类型一致注入(在多个实现类时,会产生歧义)
注意: 无论使用以上那种方式注入都需要为属性提供set方法
8.bean的创建模式
singleton:单例 默认
在工厂中全局唯一,只创建一次
prototype: 多例
全局不唯一,每次使用都会创建一个新的对象
<bean id="" class="xxxx.userAction" scope="prototype|singleton">
service,dao -----> singleton
struts2 action -----> prototype
注意:在项目开发中service,dao组件单例,struts2的Action必须为:多例
9.bean的生产原理
原理
:反射+构造方法
UserDAOImpl userDAO = (UserDAOImpl) Class.forName("com.baizhi.dao.UserDAOImpl").newInstance();
System.out.println(userDAO);
10.bean的生命周期
何时创建
随着工厂启动,
所有单例bean随之创建 非单例的bean,每次使用时创建
何时销毁
工厂
关闭,所有bean随之销毁
( 注意:spring对多例bean管理松散,不会负责多例bean的销毁
)
11.bean工厂创建对象的好处
使用配置文件管理java类,再生产环境中更换类的实现时不需要重新部署,修改文件即可
spring默认使用单例的模式创建bean,减少内存的占用
通过依赖注入建立了类与类之间的关系(使java之间关系更为清晰,方便了维护与管理)
Spring2
1.现有业务 service 层开发存在问题
a.定义业务接口
public interface UserService {
void save(String name);
void delete(String id);
void update();
String findAll(String name);
String findOne(String id);
}
b.实现业务接口
public class UserServiceImpl implements UserService {
@Override
public void save(String name) {
try {
System.out.println("开启事务");
System.out.println("处理业务逻辑,调用DAO~~~");
System.out.println("提交事务");
}catch (Exception e){
System.out.println("回滚事务");
e.printStackTrace();
}
}
@Override
public void delete(String id) {
try {
System.out.println("开启事务");
System.out.println("处理业务逻辑,调用DAO~~~");
System.out.println("提交事务");
}catch (Exception e){
System.out.println("回滚事务");
e.printStackTrace();
}
}
@Override
public void update() {
try {
System.out.println("开启事务");
System.out.println("处理业务逻辑,调用DAO~~~");
System.out.println("提交事务");
}catch (Exception e){
System.out.println("回滚事务");
e.printStackTrace();
}
}
@Override
public String findAll(String name) {
try {
System.out.println("开启事务");
System.out.println("处理业务逻辑,调用DAO~~~");
System.out.println("提交事务");
}catch (Exception e){
System.out.println("回滚事务");
e.printStackTrace();
}
return name;
}
@Override
public String findOne(String id) {
try {
System.out.println("开启事务");
System.out.println("处理业务逻辑,调用DAO~~~");
System.out.println("提交事务");
}catch (Exception e){
System.out.println("回滚事务");
e.printStackTrace();
}
return id;
}
}
问题:从上图中可以看出,现有业务层中
控制事务代码出现了大量的冗余
,如何解决现有业务层出现的冗余问题?
2.代理引言
a.什么是代理
代理
: 指的是java中的一种设计模式
b.为什么需要代理
很多时候除了当前类能够提供的功能外,我们还需要补充一些额外功能。
c.代理的作用
代理对象可以在客户和目标对象之间
起到中介作用,从而为目标对象增添额外的功能
。
d.代理图例

3.静态代理的开发
目标类|对象(target)
:被代理类称之为目标类|或者被代理的对象的称之为目标对象`开发代理的原则: 代理类和目标类功能一致且实现相同的接口,同时代理类中依赖于目标类对象`
a.开发静态代理类
//静态代理类
//开发原则:代理类和目标类实现相同接口,依赖于真正的目标类
public class UserServiceStaticProxy implements UserService {
//真正的目标类 //target 原始业务逻辑对象
private UserService userService;
public void setUserService(UserService userService) {
this.userService = userService;
}
@Override
public void save(String name) {
try {
System.out.println("开启事务");
userService.save(name);//调用真正业务逻辑方法
System.out.println("提交事务");
}catch (Exception e){
System.out.println("回滚事务");
e.printStackTrace();
}
}
@Override
public void delete(String id) {
try {
System.out.println("开启事务");
userService.delete(id);//调用真正业务逻辑方法
System.out.println("提交事务");
}catch (Exception e){
System.out.println("回滚事务");
e.printStackTrace();
}
}
@Override
public void update() {
try {
System.out.println("开启事务");
userService.update();//调用真正业务逻辑方法
System.out.println("提交事务");
}catch (Exception e){
System.out.println("回滚事务");
e.printStackTrace();
}
}
@Override
public String findAll(String name) {
try {
System.out.println("开启事务");
String result = userService.findAll(name);//调用真正业务逻辑方法
System.out.println("提交事务");
return result;
}catch (Exception e){
System.out.println("回滚事务");
e.printStackTrace();
}
return null;
}
@Override
public String findOne(String id) {
try {
System.out.println("开启事务");
//调用目标类方法
String one = userService.findOne(id);//调用真正业务逻辑方法
System.out.println("提交事务");
return one;
}catch (Exception e){
System.out.println("回滚事务");
e.printStackTrace();
}
return null;
}
}
b.更改目标实现类
public class UserServiceImpl implements UserService {
@Override
public void save(String name) {
System.out.println("处理业务逻辑,调用DAO~~~");
}
@Override
public void delete(String id) {
System.out.println("处理业务逻辑,调用DAO~~~");
}
@Override
public void update() {
System.out.println("处理业务逻辑,调用DAO~~~");
}
@Override
public String findAll(String name) {
System.out.println("处理业务逻辑,调用DAO~~~");
return name;
}
@Override
public String findOne(String id) {
System.out.println("处理业务逻辑,调用DAO~~~");
return id;
}
}
c.配置静态代理类
<!--配置目标类-->
<bean id="userService" class="staticproxy.UserServiceImpl"></bean>
<!--配置代理类-->
<bean id="userServiceStaticProxy" class="staticproxy.UserServiceStaticProxy">
<!--注入目标对象-->
<property name="userService" ref="userService"/>
</bean>
d.调用代理方法
ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
UserService userServiceStaticProxy = (UserService) context.getBean("userServiceStaticProxy");
userServiceStaticProxy.save("小黑");
新的问题:
往往在开发我们书写的不仅仅是一个业务层,两个业务层,而我们的业务层会有很多,如果为每一个业务层开发一个静态代理类,不仅没有减轻工作量,甚至让我们的工作量多了一倍不止怎么解决以上这个问题呢?
解决方案:
为业务层在运行过程中动态创建代理类,通过动态代理类去解决我们现有业务层中业务代码冗余的问题
.
4.动态代理的原理
通过jdk提供的Proxy这个类,动态为现有的业务生成代理类
参数一:当前线程类加载器 参数二:生成代理类的接口类型 参数三:通过代理类对象调用方法时会优先进入参数三中的invoke方Proxy.newProxyInstance(loader, interfaces, h);//返回值就是动态代理对象
public class TestDynamicProxy {
public static void main(String[] args) {
final UserService userService = new UserServiceImpl();
//参数1:当前线程类加载器
ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
//参数2:
Class[] classes = new Class[]{UserService.class};
//参数3:
UserService userServiceProxy = (UserService) Proxy.newProxyInstance(contextClassLoader, classes, new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
try{
System.out.println("开启事务");//附加操作
Object invoke = method.invoke(userService, args);
System.out.println("提交事务");//附加操作
return invoke;
}catch (Exception e){
System.out.println("回滚事务");//附加操作
}
return null;
}
});
userServiceProxy.save("小黑");
}
}
5.AOP (Aspect Oriented Programming)编程
通知(Advice)
:除了目标方法以外的操作都称之为通知
`切入点(PointCut): 要为哪些类中的哪些方法加入通知` `切面(Aspect)`: `通知 + 切入点`
1.通知分类

2.编程步骤
# 1.引入依赖
spring-aop
spring-expression
spring-aspects
# 2.开发通知类
MethodBeforeAdvice 前置通知
MethodInterceptor 环绕通知
AfterReturningAdvice 返回后通知
ThrowsAdvice 异常通知
MyAdvice implements 通知接口{.....}
//自定义通知类:用来完成额外功能
public class MyAdvice implements MethodBeforeAdvice {
@Override//参数1:当前调用的方法对象 //参数2:当前调用方法对象的参数 //参数3:
public void before(Method method, Object[] objects, Object o) throws Throwable {
System.out.println("目标方法名: "+method.getName());
System.out.println("目标方法的参数: "+objects);
System.out.println("目标对象: "+o.getClass());
}
}
# 3.配置切面
a.引入aop命名空间
<?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"
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">
b.管理通知
<!--管理通知类-->
<bean id="myAdvice" class="before.MyAdvice"/>
c.配置切面
<aop:config>
<aop:pointcut id="pc" expression="execution(* before.UserServiceImpl.*(..))"/>
<aop:advisor advice-ref="myAdvice" pointcut-ref="pc"/>
</aop:config>
# 4.启动工厂测试
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("before/spring.xml");
UserService userSerivce = (UserService) context.getBean("userService");
System.out.println(userSerivce.getClass());
userSerivce.save("小黑");
3.前置通知的使用

4.环绕通知的使用

5.返回后通知

6.异常通知

6.切入点表达表
1.execution方法级别的切入点表达式

注意:方法级别的切入点表达式尽可能精准,否则程序运行可能出现异常
2.within类级别的切入点表达式
# 1.语法
within(包.类)
# 2.示例
within(com.baizhi.service.*)
包: com.baizhi.service
类: 所有类中所有方法不关心返回值和参数
within(com.baizhi.service.UserServiceImpl)
包: com.baizhi.service
类: UserServiceImpl类中所有方法不关心返回值和参数
注意:within的效率高于execution表达式,推荐使用within表达式
Spring3
1.创建复杂对象
复杂对象
: 类中没有构造方法,或者构造方法不能调用如接口类型或抽象类实例
//1.类 implements FactoryBean<创建的类型>
public class ConnectionFactoryBean implements FactoryBean<Connection> {
@Override
public Connection getObject() throws Exception {
Class.forName("com.mysql.jdbc.Driver");
return DriverManager.getConnection("jdbc:mysql://localhost:3306/test","root","root");
}
@Override
public Class<?> getObjectType() {
return Connection.class;
}
@Override
public boolean isSingleton() {
return false;
}
}
// 2.配置工厂管理
<bean id="connectionFactoryBean" class="com.baizhi.factorybean.ConnectionFactoryBean"></bean>
// 3.获取复杂对象
ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
Connection conn = (Connection) context.getBean("connectionFactoryBean");
System.out.println(conn);
2.SM整合思路
1.spring框架的作用
spring框架 项目管理框架 主要负责项目中组件对象的创建
2.Mybatis框架的作用
Mybatis框架 持久层框架 主要用来简化数据库访问的操作
3.整合思路
整合思路: 两个框架作用不同,貌似没有什么联系,更深入看才能看出所谓Spring整合Mybatis,其实就是通过spring框架接管mybatis框架中核心对象的创建
4.mybatis中的核心对象有哪些
Mybatis的核心对象为: SqlSessionFactory
整合就是通过Spring管理SqlSessionFactory对象的创建
5.整合思路图示

2.SM整合DAO编程步骤
1.引入mybatis的依赖jar包
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.2.8</version>
</dependency>
2.引入Spring相关jar包
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>4.3.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.3.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>4.3.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>4.3.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>4.3.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>4.3.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-expression</artifactId>
<version>4.3.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>4.3.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>4.3.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>4.3.2.RELEASE</version>
</dependency>
3.mybatis-spring整合jar
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.3.1</version>
</dependency>
4.引入数据库驱动jar
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.40</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.12</version>
</dependency>
5.建表
CREATE TABLE `t_user` (
`id` varchar(40) NOT NULL,
`name` varchar(40) DEFAULT NULL,
`age` int(3) DEFAULT NULL,
`bir` timestamp NULL DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
6.编写实体类
public class User {
private String id;
private String name;
private Integer age;
private Date bir;
//......
}
7.书写DAO接口
public interface UserDAO {
//查询所有
List<User> findAll();
}
8.编写mapper配置文件
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.baizhi.dao.UserDAO">
<select id="findAll" resultType="com.baizhi.entity.User">
select id,name,age,bir from t_user
</select>
</mapper>
9.编写Spring-myabtis整合配置文件
<!--创建数据源-->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/sm"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</bean>
<!--创建sqlSessionFactory-->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="mapperLocations" >
<array>
<value>classpath:com/baizhi/mapper/UserDAOMapper.xml</value>
</array>
</property>
</bean>
<!--创建DAO-->
<bean id="userDAO" class="org.mybatis.spring.mapper.MapperFactoryBean">
<property name="sqlSessionFactory" ref="sqlSessionFactory"/>
<property name="mapperInterface" value="com.baizhi.dao.UserDAO"/>
</bean>
10.启动工厂测试
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
UserDAO userDAO = (UserDAO) context.getBean("userDAO");
List<User> users = userDAO.findAll();
for (User user : users) {
System.out.println(user);
}
3.SM整合Service编程步骤
1.编写spring-mybatis.xml配置文件
<!--创建事务管理器-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<!--配置事务属性-->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="save*"/>
<tx:method name="update*"/>
<tx:method name="delete*"/>
<tx:method name="find*"/>
</tx:attributes>
</tx:advice>
<!--配置事务切面-->
<aop:config>
<aop:pointcut id="pc" expression="within(com.baizhi.service.*)"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="pc"/>
</aop:config>
2.配置图示

3.创建service接口
public interface UserService {
List<User> findAll();
}
4.创建service对象
public class UserServiceImpl implements UserService {
private UserDAO userDAO;
public void setUserDAO(UserDAO userDAO) {
this.userDAO = userDAO;
}
@Override
public List<User> findAll() {
return userDAO.findAll();
}
}
5.配置业务组件对象
<!--配置Service组件-->
<bean id="userService" class="com.baizhi.service.UserServiceImpl">
<property name="userDAO" ref="userDAO"/>
</bean>
6.启动测试
4.事务属性
1.事务传播属性
# propagation: 传播
REQUIRED: 需要事务,外部存在事务融入当前事务,外部没有事务,开启新的事务
SUPPORTS: 支持事务,外部存在事务融入当前事务,外部没有事务,不开启新的事务
REQUIRES_NEW: 每次开启新的事务,如果外部存在事务外部事务挂起,开启新的事务运行,运行结束后回复外部事务
NOT_SUPPORTED: 不支持事务,如果外部存在事务外部事务挂起,已非事务方式运行.
NEVER: 不支持事务,存在事务报错
MANDATORY: 强制事务没有事务报错
NESTED: 嵌套事务,数据库不支持
2.事务的隔离级别
# isolation 隔离级别
DEFAULT: 采用数据库默认隔离级别
READ_UNCOMMITTED: 读未提交
READ_COMMITTED: 读提交 用来避免脏读现象出现的 oracle默认隔离级别
REPEATABLE_READ: 可重复读主要是用来避免不可重复读现象出现的 (在一次事务中一方更新,导致两次查询结果不一致这种情况叫不可重复读) mysql默认隔离级别
SERIALIZABLE : 序列化读 用来避免幻影读现象出现 (在一次事务中一方插入,导致两次查询结果不一致这种情况叫幻影读)
3.读写和异常性
# readonly
`true: 本次事务只读
`false: 本次事务非只读
<tx:method name="save*" propagation="REQUIRES_NEW" read-only="true|false" isolation="SERIALIZABLE"/>
# rollback-for && no-rollback-for=""
rollback-for: 遇到什么类异常回滚
no-rollback-for: 遇到什么类异常不回滚
<tx:method name="save*" rollback-for="" no-rollback-for="" propagation="REQUIRES_NEW" read-only="true" isolation="SERIALIZABLE"/>
# timeout 超时性
timeout: -1 永不超时
Spring4
1.Spring整合Struts2框架
1.引入依赖
需要引入:
struts2
Spring
Struts2-Spring-plugin
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>4.3.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.3.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>4.3.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>4.3.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>4.3.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>4.3.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-expression</artifactId>
<version>4.3.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>4.3.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>4.3.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>4.3.2.RELEASE</version>
</dependency>
2.配置web.xml
配置struts2核心控制器
<filter>
<filter-name>struts2</filter-name>
<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
配置spring启动工厂
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
加载工厂配置文件
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring.xml</param-value>
</context-param>
3.开发Action
public class UserAction {
public String findAll(){
System.out.println("hello action~~ ");
return Action.SUCCESS;
}
}
4.工厂管理Action组件
<!--管理Action-->
<bean id="userAction" class="com.baizhi.action.UserAction"></bean>
5.配置struts.xml
<package name="user" extends="struts-default" namespace="/user">
<action name="findAll" class="userAction" method="findAll">
<result name="success">/index.jsp</result>
</action>
</package>
注意:
`配置文件中书写的是工厂中管理的action的bean的id`
6.部署项目测试
2.Spring的注解式开发
注解: Annotation
注解开发: 为了去提高现有配置文件开发的开发效率
1.开启注解扫描配置
<!--开启注解扫描-->
<context:component-scan base-package="com"/>
2.实例化相关注解
Spring自2.5版本以后提供了一些注解用来在使用spring时进行快速开发
# 1. @Component(value="beanid")
修饰范围: 用在类上
注解作用: 通用的创建实例的注解,用来创建当前这个类的实例
value属性: 用来指定创建的对象在工厂中的唯一标识 如果不指定默认创建对象在工厂中的标识为类名首字母小写
# 2. @Repository
修饰范围: 用在类上
注解作用: @component的子类注解专用于DAO组件的创建,通常加在DAO组件上
value属性: 用来指定创建的对象在工厂中的唯一标识 如果不指定默认创建对象在工厂中的标识为类名首字母小写
# 3. @Service
修饰范围: 用在类上
注解作用: @component的子类注解专用于Service组件的创建,通常加在Service组件上
value属性: 用来指定创建的对象在工厂中的唯一标识 如果不指定默认创建对象在工厂中的标识为类名首字母小写
# 4. @Controller
修饰范围: 用在类上
注解作用: @component的子类注解专用于Action组件的创建,通常加在Action组件上
value属性: 用来指定创建的对象在工厂中的唯一标识 如果不指定默认创建对象在工厂中的标识为类名首字母小写
3.控制对象的创建次数的注解
# 1. @Scope(value="singleton|prototype")
修饰范围: 用在类上
注解作用: 用来控制这个实例在工厂中的创建次数
value属性: singleton为单例,prototype为多例 默认单例
4.注入相关的注解
# 1. @Autowired(Spring提供)
修饰范围: 用在成员变量或成员变量的GET/SET方法上
注解作用: 用来给类中成员变量赋值
注入原则: 默认根据类型自动注入
# 2. @Resource(JAVAEE提供)
修饰范围: 用在成员变量或成员变量的GET/SET方法上
注解作用: 用来给类中成员变量赋值
注入原则: 默认根据名称自动注入名称找不到根据类型自动注入
5.控制事务的相关注解
# 1. @Transactional
修饰范围: 用在类上主要用在业务层组件类上或者是方法上
注解作用: 用来给类中方法加入事务,当类上和方法上同时存在该注解时局部优先
注解属性:
propagation 用来控制传播属性
Isolation 用来控制隔离级别
timeout 用来设置超时性
rollback-for 用来设置什么异常回滚
norollback-for 用来设置什么异常不会滚
readonly 用来设置事务读写性
注意:如果要使用事务注解在配置文件中必须开启事务注解生效加入如下配置:
<tx:annotation-driven transaction-manager="transactionManager"></tx:annotation-driven>