组件扫描
它是Spring 提供的一套基于标注(注解)的技术
目的是为了简化XML的配置
Spring中实现组件扫描的步骤
1 建立一个项目 导入jar包(ioc aop) 拷贝spring 配置文件到src下
2 在spring 配置文件中 开启组件扫描
<context:component-scan base-package="包名" />
3 编写java 类 在类上加对应的标注
@Repository 持久层标注
@Controller 控制层标注
@Service 服务层标注
@Component 通用层标注
4 创建Spring 容器 从容器中获取对应的组件
和组件扫描相关的标注
@Scope("singleton|prototype") 控制组件的作用域
@@PostConstruct 和初始化相关的标注
@PreDestroy 和销毁相关的标注
和DI相关的标注
1 @Value
这个标注可以用在 成员变量 和 set方法上
一般用来解决简单值的注入问题 如果要注入复杂值 则需要结合EL表达式
2 @Autowired
这个标注可以用在 成员变量 set方法 构造方法上
用来解决复杂值的注入问题
这个标注优先按照类型进行匹配 如果类型对应有多个对象 则会启用对象的名字进行匹配
@Qualifier("名字") 可以加载指定组件 但是这个标注不能用在构造方法上
@Autowired 中 结合 @Qualifier("名字") 对组件的依赖属于强依赖(依赖的组件必须存在 如果不存在程序崩溃 )
可以使用@Autowired 的 requried 属性 设置成false 则代表尽量去查找组件 找不到也不报错。
@Resource
这个标注 可以用在成员变量 和 set方法上
用来解决复杂值的注入问题的
这个标注优先按照名字进行匹配 如果没有同名的组件 则启用类型进行匹配
@Resource 这个标注是JDK中的标注
这个标注不能解除强依赖的问题
Spring DAO
Spring DAO 封装了JDBC 简化了DAO 实现的类编写
Spring DAO 提供了 基于 AOP的事务管理
Spring DAO 对JDBC 中的异常 做了封装 把原来检查异常 封装成了 继承 自RuntimeException的 一个DataAccessException
Spring DAO 中的核心类
JdbcTemplate jdbc模板类
可以自动加载驱动 获取连接 执行环境的获取 结果集遍历 以及资源的释放
JdbcDaoSupport jdbc DAO的支持类
这个类可以提供JdbcTemplate 模板对象
采用继承JdbcDaoSupport的方式完成对数据库的操作
0 建立一张数据库表 插入几条测试数据 提交
1 建立一个项目 导入jar包(ioc aop dao 连接池 数据库驱动 ) 拷贝配置文件到src
<!-- 开启组件扫描 -->
<context:component-scan base-package="com.xdl"></context:component-scan>
<!-- 连接池对象的配置 -->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" >
<value>oracle.jdbc.OracleDriver</value>
</property>
<property name="url"
value="jdbc:oracle:thin:@127.0.0.1:1521:orcl"></property>
<property name="username" value="liziyang"></property>
<property name="password" value="123"></property>
</bean>
2 编写DAO 接口 查询银行账户表中的账户的数量
3 编写DAO 的实现类 继承 JdbcDaoSupport 实现DAO 接口 使用父类提供的模板 结合sql 语句 完成查询
Mapper类
public class Mapper implements RowMapper<Bnak> {
@Override
public Bnak mapRow(ResultSet rs, int index) throws SQLException {
Bnak bank = new Bnak(
rs.getInt("bid"), rs.getString("name"), rs.getString("pass"), rs.getDouble("money"));
return bank;
}
}
@Repository("bankDao")
public class BankDaoImpl extends JdbcDaoSupport implements BankDao {
@Autowired
public BankDaoImpl(DataSource dataSource) {
super.setDataSource(dataSource);
}
@Override
public String QueryById(String id) {
String sql = "select pass from bank where bid = ?";
return super.getJdbcTemplate().queryForObject(sql, String.class, id);
}
@Override
public List<Bnak> QueryAll() {
String sql = "select * from bank";
return super.getJdbcTemplate().query(sql,new Mapper());
}
}
4 开启组件 在DAO 实现类上 打持久层标注 同时 要 给JdbcDaoSupport 注入一个dataSource 对象
5 创建Spring 容器 获取DAO 并进行测试
public static void main(String[] args) {
ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
BankDao bd =app.getBean("bankDao", BankDao.class);
System.out.println(bd.delete("1"));
}
Spring DAO 如何完成 增删改(DML)
1 增加银行账户
a.建表 如果有需要建立对应的序列
b.建立项目 导入jar包(ioc aop dao 数据库连接池 和 驱动) 拷贝配置文件到src下
c.编写一个实体bean
d.编写DAO 接口
e.编写DAO 的实现类 继承JdbcDaoSupport 实现DAO 接口 使用父类模板 根据sql 完成对应的操作
f.开启组件扫描 给DAO的父类注入dataSource
g.封装一个Service 注入DAO 封装业务方法 ----测试
2 删除逻辑的编写
a.建表 如果有需要建立对应的序列
b.建立项目 导入jar包(ioc aop dao 数据库连接池 和 驱动) 拷贝配置文件到src下
c.编写一个实体bean
d.编写DAO 接口
e.编写DAO 的实现类 继承JdbcDaoSupport 实现DAO 接口 使用父类模板 根据sql 完成对应的操作
f.开启组件扫描 给DAO的父类注入dataSource
g.封装一个Service 注入DAO 封装业务方法 ----测试
service方法
@Service("BankService")
public class BankService {
@Autowired
private BankDao bankDao;
public int querycount() {
return bankDao.querycount();
}
}
不继承JdbcDaoSupport的方式完成 Spring 对数据库的操作
需要自己定义一个JdbcTemplate 类型的对象 然后注入给DAO的实现类 使用自定义的模板对象完成对应的数据库操作。
当然自定义模板对象 需要注入dataSource 。
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<constructor-arg index="0" ref="dataSource"></constructor-arg>
</bean>
Spring 的声明式事务
1 在Spring 的配置文件中开启声明式事务
<tx:annotation-driven transaction-manager="事务管理器id" proxy-target-class="false" />
proxy-target-class 默认使用SUN公司的代理机制 如果产生不了 则启用CGLIB
如果 proxy-target-class="true" 则直接使用CGLIB 的代理机制
2 创建事务管理器组件 ----- 注意这个组件需要依赖于 dataSource
BankDaoImpl类
@Autowired
private JdbcTemplate jdbcTemplate;
<!-- 创建事务管理器 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
3 在类上 或者在业务方法加事务控制标注 @Transactional
@Transactional 的属性
rollbackFor Spring 的声明式事务默认只针对运行时异常回滚 对检查异常不回滚 可以通过
rollbackFor 属性指定对应的检查异常进行回滚
noRollbackFor 针对指定的运行时异常不回滚
readOnly 只读事务 当事务中只有查询语句时 可以把readOnly设置成true 代表只读事务
只要有DML操作 设置成true 无效
isolation 隔离 用来设置事务的隔离级别的
事务的隔离级别 读未提交 读提交 可重复读 序列化
用来解决数据库中的三大读问题:
脏读: 一个事务读取到了另外一个事务没有提交的数据
不可重复读:一个事务在开始时读取了一份数据 另外一个事务修改了这份数据 并进行了提交
当第一个事务再次读取数据发现数据发生了改变 这叫不可重读读。
幻读:一个事务统计了整张表的数据 另外一个事务 对表增加了数据 并进行了提交 当第一个事务再次统计
数据时发现数据发生了改变。
propagation 事务传播特性
一个方法去调用一个事务方法时 事务应该如何表现
Propagation.REQUIRED 如果当前方法不存在事务 则会开启新事物 如果当前方法存在事务则加入到当前事务之中
Propagation.requierd:如果当前没有事务,就新建一个事务,如果已存在一个事务中,加入到这个事务中,这是最常见的选择。
Propagation_supports:支持当前事务,如果没有当前事务,就以非事务方法执行。
Propagation_mandatory:使用当前事务,如果没有当前事务,就抛出异常。
Propagation_required_new:新建事务,如果当前存在事务,把当前事务挂起。
Propagation_not_supported:以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
Propagation_never:以非事务方式执行操作,如果当前事务存在则抛出异常。
Propagation_nested:如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与propagation_required类似的操作