1. Spring介绍
Spring的核心是控制反转(IoC)和面向切面(AoP)。
总共分为三层结构:
- WEB层:Spring MVC
- 业务层:Bean管理(IOC)
- 持久层:Spring的JDBC模板,ORM模板用于整个其他的持久层框架
Spring 的Bean属性注入:
1.1 Sping架构
-
核心容器:核心容器提供 Spring 框架的基本功能。核心容器的主要组件是 BeanFactory,它是工厂模式的实现。BeanFactory 使用控制反转 (IOC) 模式将应用程序的配置和依赖性规范与实际的应用程序代码分开。
-
Spring 上下文:Spring 上下文是一个配置文件,向 Spring 框架提供上下文信息。Spring 上下文包括企业服务,例如 JNDI、EJB、电子邮件、国际化、校验和调度功能。
Spring AOP:通过配置管理特性,Spring AOP 模块直接将面向方面的编程功能集成到了 Spring 框架中。所以,可以很容易地使 Spring 框架管理的任何对象支持 AOP。Spring - - AOP 模块为基于 Spring 的应用程序中的对象提供了事务管理服务。通过使用 Spring AOP,不用依赖 EJB 组件,就可以将声明性事务管理集成到应用程序中。 -
Spring DAO:JDBC DAO 抽象层提供了有意义的异常层次结构,可用该结构来管理异常处理和不同数据库供应商抛出的错误消息。异常层次结构简化了错误处理,并且极大地降低了需要编写的异常代码数量(例如打开和关闭连接)。Spring DAO 的面向 JDBC 的异常遵从通用的 DAO 异常层次结构。
-
Spring ORM:Spring 框架插入了若干个 ORM 框架,从而提供了 ORM 的对象关系工具,其中包括 JDO、Hibernate 和 iBatis SQL Map。所有这些都遵从 Spring 的通用事务和 DAO 异常层次结构。
-
Spring Web 模块:Web 上下文模块建立在应用程序上下文模块之上,为基于 Web 的应用程序提供了上下文。所以,Spring 框架支持与 Jakarta Struts 的集成。Web 模块还简化了处理多部分请求以及将请求参数绑定到域对象的工作。
-
Spring MVC 框架:MVC 框架是一个全功能的构建 Web 应用程序的 MVC 实现。通过策略接口,MVC 框架变成为高度可配置的,MVC 容纳了大量视图技术,其中包括 JSP、Velocity、Tiles、iText 和 POI。
1.2 Spring配置
- 依赖包的注入
- 引入相关的配置文件
<beans xmlns="http://www.springframework.org/schema/beans"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd "
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
>
//引入约束
<!--将User对象交给Spring容器管理-->
<!--Bean元素;使用该元素描述需要spring容器管理的对象-->
<bean name="user" class="cn.raine.bean.User"></bean>
</beans>
1.3 Spring的工厂 (容器)
ApplicationContext
和BeanFactory
(在内存资源少的时候使用已过时)
区别:
BeanFactory :是在 getBean 的时候才会生成类的实例.
ApplicationContext :在加载 applicationContext.xml(容器启动)时候就会创建.
获取容器
//创建容器对象
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
User u = (User) ac.getBean("user");
System.out.print(u);
1.4 Spring相关配置属性
- id属性:Bean 起个名字. 在约束中采用 ID 的约束:唯一. 必须以字母开始,可以使用字母、数字、连字符、 下划线、句话、冒号 id:不能出现特殊字符.
- name属性:Bean 起个名字. 没有采用 ID 的约束. name:出现特殊字符.如果
<bean>
没有 id 的话 , name 可 以当做 id 使用. - scop属性
- singleton : 默认值,单例的
- prototype: 多例的
1.4.1 Bean的生命周期
通过配置<bean>
标签上的init-method
作为 Bean 的初始化的时候执行的方法,配置 destroy-method
作为 Bean 的销毁的时候执行的方法。 销毁方法想要执行,需要是单例创建的 Bean 而且在工厂关闭的时候,Bean 才会被销毁
1. 5 Spring的注入
- Spring的bean的属性注入
- 构造方法的注入方式
<!-- 第一种:构造方法的方式 -->
<bean id="car" class="cn.itcast.spring.demo4.Car">
<constructor-arg name="name" value=" 保时捷 "/>
<constructor-arg name="price" value="1000000"/>
</bean>
- set方法的注入属性
<!-- 第二种:set 方法的方式 -->
<bean id="car2" class="cn.itcast.spring.demo4.Car2">
<property name="name" value=" 奇瑞 QQ"/>
<property name="price" value="40000"/>
</bean>
- 对象类型的注入
<!-- 注入对象类型的属性 -->
<bean id="person" class="cn.itcast.spring.demo4.Person">
<property name="name" value=" 会希 "/>
<!-- ref 属性:引用另一个 bean 的 id 或 name -->
<property name="car2" ref="car2"/>
</bean>
- 复杂类型的注入
<!--复杂类型的注入-->
<bean name="cb" class="cn.raine.injection.CollectionBean">
<property name="arr">
<list>
<value>会希</value>
<value>哈哈</value>
</list>
</property>
<property name="list">
<list>
<value>javck</value>
<value>jerry</value>
<ref bean="user2"></ref>
</list>
</property>
</bean>
构造函数注入的时候:
//确定使用哪个构造函数
<constructor-arg name="name" index="0" type="java.lang.Interger"/>
listener是spring web 包
2. AOP
2.1 使用注解配置Spring
头部约束
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
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-4.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd"
>
xml中写入
<!--指定扫描cn.raine.bean下的所有类的注解
注意:扫描包时,会扫描指定包下所有的子包
-->
<context:component-scan base-package="cn.raine.bean"></context:component-scan>
代码注解
//将对象注入到容器
Component("user")
Service("user") //Service层
Controller("user") //web层
@(后台)Repository("user") //dao层
//值类型的注入
@Value("tom")
public void setNmae(String name){
...
}
//引用类型的注入
@Autowired //自定装配
private Car car;
@Resource(name="car") //手动注入,指定注入哪个名称的对象
private Car car;
Spring 的 Bean 管理的方式的比较
2.2 Sping接入整合Junit测试
RunWith(SpringJUnit4ClassRunner.class) //帮我们创建容器
@ContextConfiguration("classpath:applicationContext.xml")
public class Demo {
@Resource(name = "user")
private User u;
@Test
public void fun1(){
}
2.3 Sping的AOP介绍
2.3.1 底层实现
代理机制
- Spring的AOP的底层用到两种代理机制:
- JDK的动态代理:针对实现了接口的产生代理
- Cglib的到动态代理:针对没有实现接口的类产生代理,应用的是底层的字节码增强的技术,深层当前类的子类对象。
2.3.2 AOP的开发中的相关术语
- Joinpoint(连接点):所谓连接点是指那些被拦截到的点。在 spring 中,这些点指的是方法,因为 spring 只 支持方法类型的连接点.
- Pointcut(切入点):所谓切入点是指我们要对哪些 Joinpoint 进行拦截的定义.
- Advice(通知/增强):所谓通知是指拦截到 Joinpoint 之后所要做的事情就是通知.通知分为前置通知,后置 通知,异常通知,最终通知,环绕通知(切面要完成的功能)
- Introduction(引介):引介是一种特殊的通知在不修改类代码的前提下, Introduction 可以在运行期为类 动态地添加一些方法或 Field.
- Target(目标对象):代理的目标对象
- Weaving(织入):是指把增强应用到目标对象来创建新的代理对象的过程. spring 采用动态代理织入,而 AspectJ 采用编译期织入和类装在期织入
- Proxy(代理):一个类被 AOP 织入增强后,就产生一个结果代理类
- Aspect(切面): 是切入点和通知(引介)的结合
2.3.2 AOP的开发
jar包介绍
步骤
<!--准备工作:导入aop(约束)命名空间-->
<!--1.配置目标对象-->
<!--2.配置通知对象-->
<!--3.配置将通知织入目标对象-->
<!-- 配置切入点
* cn.itcast.service..*ServiceImpl.*(..)
这个service包下面的任意子包中以ServiceImpl结尾的任意类中的任意方法(任意参数) 可以返回任意类型数据
-->
前置通知 :在目标方法执行之前执行.
后置通知 :在目标方法执行之后执行
环绕通知 :在目标方法执行前和执行后执行
异常抛出通知:在目标方法执行出现 异常的时候 执行
最终通知 :无论目标方法是否出现异常 最终通知都会 执行.
目标类的创建:
//创建接口和类:
public interface OrderDao {
public void save();
public void update();
public void delete();
public void find();
}
public class OrderDaoImpl implements OrderDao {
@Override public void save() {
System.out.println("保存订单...");
@Override public void update() {
System.out.println("修改订单..."); }
@Override public void delete() {
System.out.println("删除订单..."); }
@Override public void find() {
System.out.println("查询订单..."); }
}
}
目标类的配置
<!-- 目标类================ -->
<bean id="orderDao" class="cn.itcast.spring.demo3.OrderDaoImpl"> </bean>
整合Jubit单元测试
引入 spring-test.jar
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class SpringDemo3 {
@Resource(name="orderDao")
private OrderDao orderDao;
@Test
public void demo1(){
orderDao.save();
orderDao.update();
orderDao.delete();
orderDao.find();
} }
编写切入面
public class MyAspectXml {
// 前置增强
public void before(){
System.out.println("前置增强===========");
} }
配置完成增强
<!-- 配置切面类 -->
<bean id="myAspectXml" class="cn.itcast.spring.demo3.MyAspectXml"></bean>
<!-- 进行 aop 的配置 -->
<aop:config>
<!-- 配置切入点表达式:哪些类的哪些方法需要进行增强 -->
<aop:pointcut expression="execution(* cn.itcast.spring.demo3.OrderDao.save(..))" id="pointcut1"/>
<!-- 配置切面 -->
<aop:aspect ref="myAspectXml">
<aop:before method="before" pointcut-ref="pointcut1"/>
</aop:aspect>
</aop:config>
切入点表达式:
execution(表达式)
表达式: [方法访问修饰符] 方法返回值 包名.类名.方法名(方法的参数)
public * cn.itcast.spring.dao.*.*(..)
* cn.itcast.spring.dao.*.*(..)
* cn.itcast.spring.dao.UserDao+.*(..)
* cn.itcast.spring.dao..*.*(..)
3. Spring整合JDBC
3.1 Spring连接JDBC
导入jar包
编写Dao文件
public class UserDaoImpl extends JdbcDaoSupport implements UserDao {
//引入了JDBCDaoSupport根据连接池创建JDBC模板,直接从父类方法中获得就可以了
@Override
public void save(User u) {
String sql = "insert into s_user values(null, ?)";
getJdbcTemplate().update(sql, u.getName());
}
@Override
public void delete(Integer id) {
String sql = "delete from s_user where id =?";
getJdbcTemplate().update(sql, id);
}
@Override
public void update(User u) {
String sql = "update s_user set name = ? where id = ?";
getJdbcTemplate().update(sql, u.getName(), u.getId());
}
//查询单个对象
@Override
public User getById(Integer id) {
String sql = "select * from s_user where id = ?";
return getJdbcTemplate().queryForObject(sql, new RowMapper<User>() {
@Override
public User mapRow(ResultSet rs, int i) throws SQLException {
User u = new User();
u.setId(rs.getInt("id"));
u.setName(rs.getString("name"));
return u;
}
});
}
//查询值类型
@Override
public int getTotalCount() {
String sql = "select count(*) from t_user ";
Integer count = super.getJdbcTemplate().queryForObject(sql, Integer.class);
return count;
}
//查询list集合类型
@Override
public List<User> getAll() {
String sql = "select * from s_user";
List<User> list = getJdbcTemplate().query(sql, new RowMapper<User>() {
@Override
public User mapRow(ResultSet rs, int i) throws SQLException {
User u = new User();
u.setId(rs.getInt("id"));
u.setName(rs.getString("name"));
return u;
}
});
return list;
}
}
Spring配置
<!--指定spring读取db.properties配置-->
<context:property-placeholder location="classpath:db.properties"/>
<!--指定spring读取db.properties配置-->
<bean name="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="jdbcUrl" value="${jdbc.jdbcUrl}"></property>
<property name="driverClass" value="${jdbc.driverClass}"></property>
<property name="user" value="${jdbc.user}"></property>
<property name="password" value="${jdbc.password}"></property>
</bean>
<!--将JDBCTemplate放入spring容器-->
<bean name="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- 3.将UserDao放入spring容器 -->
<bean name="userDao" class="cn.raine.jsbctemplate.UserDaoImpl">
<property name="dataSource" ref="dataSource"></property>
</bean>
3.2 事务
3.2.1 事务特性
- 原子性 :强调事务的不可分割.
- 一致性 :事务的执行的前后数据的完整性保持一致.
- 隔离性 :一个事务执行的过程中,不应该受到其他事务的干扰
- 持久性 :事务一旦结束,数据就持久到数据库
3.2.2设置事务隔离级别
- 未提交读 :脏读,不可重复读,虚读都有可能发生
- 已提交读 :避免脏读。但是不可重复读和虚读有可能发生
- 可重复读 :避免脏读和不可重复读.但是虚读有可能发生.
- 串行化的 :避免以上所有读问题.
####3.2.3 真正管理事务的对象
***** 真正管理事务的对象
org.springframework.jdbc.datasource.DataSourceTransactionManager 使用 Spring JDBC 或 iBatis 进行持久化数据时使用
org.springframework.orm.hibernate3.HibernateTransactionManager 使用 Hibernate 版本进行持久化数据时使用
3.2.4 事务的传播行为
PROPAGION_XXX :事务的传播行为
-
保证同一个事务中
PROPAGATION_REQUIRED 支持当前事务,如果不存在 就新建一个(默认) PROPAGATION_SUPPORTS 支持当前事务,如果不存在,就不使用事务
PROPAGATION_MANDATORY 支持当前事务,如果不存在,抛出异常 -
保证没有在同一个事务中
PROPAGATION_REQUIRES_NEW 如果有事务存在,挂起当前事务,创建一个新的事务
PROPAGATION_NOT_SUPPORTED 以非事务方式运行,如果有事务存在,挂起当前事务
PROPAGATION_NEVER 以非事务方式运行,如果有事务存在,抛出异常
PROPAGATION_NESTED 如果当前事务存在,则嵌套事务执行
3.2.5 Spring管理事务方式
3.2.5.1 xml配置
xml配置
<!--事务核心管理器,封装了所欲事务操作,依赖于连接池-->
<bean name="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!--事务模板对象-->
<bean name="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate">
<property name="transactionManager" ref="transactionManager"></property>
</bean>
<!--配置事务通知-->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<!-- 以方法为单位,指定方法应用什么事务属性
isolation:隔离级别
propagation:传播行为
read-only:是否只读-->
<tx:method name="save" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false"/>
<tx:method name="transfer" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false" />
</tx:attributes>
</tx:advice>
<!--配置织入-->
<aop:config>
<!--配置切点表达式-->
<aop:pointcut id="txPc" expression="execution(* cn.raine.service.*ServiceImpl.*(..))" />
<!-- 配置切面 : 通知+切点
advice-ref:通知的名称
pointcut-ref:切点的名称
-->
<aop:advisor advice-ref="txAdvice" pointcut-ref="txPc"/>
</aop:config>
<bean name="accountDao" class="cn.raine.dao.AccountDaoImpl">
<property name="dataSource" ref="dataSource"></property>
</bean>
<bean name="accountService" class="cn.raine.service.AccountServiceImpl">
<property name="ad" ref="accountDao"></property>
<property name="tt" ref="transactionTemplate"></property>
</bean>
在Service中调用模板
public void transfer(Integer from, Integer to, Double money) {
tt.execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(TransactionStatus transactionStatus) {
//减钱
ad.decreaseMoney(from, money);
//加钱
ad.increaseMoney(to, money);
}
});
3.2.5.2 注解配置
开启注解管理事务
<!--开启使用注解管理aop事务-->
<tx:annotation-driven/>
使用注解
@Override
@Transactional(isolation = ![这里写图片描述](http://img.blog.csdn.net/20171210101028916?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvTGVicm9uX3hpYQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)Isolation.REPEATABLE_READ, propagation = Propagation.REQUIRES_NEW, readOnly = false)
public void transfer(Integer from, Integer to, Double money) {
//减钱
ad.decreaseMoney(from, money);
// int i = 1/0;
//加钱
ad.increaseMoney(to, money);
}