1. Spring概念
- Spring是一个项目管理框架,同时也是一套JavaEE解决方案。
- Sping是众多优秀设计模式的组合(工厂、单例、代理、适配器、包装器、观察者、模板、策略)。
- Spring并未替代现有框架产品,而是将众多框架进行有机整合,简化企业级开发,俗称“胶水框架”。
框架概述
LOC :控制反转,把创建对象过程交给Spring进行管理。
AOP 面向切片,不修改源代码进行工程增强。
- Spring IOC 解决的是 对象管理和对象依赖的问题。
- Spring AOP 解决的是 非业务代码抽取的问题。
2. Spring环境搭建
- 添加Spring依赖
3. 测试Spring工厂类
1. 增加DAO类
增加services类
- 增加Spring配置
- 测试spring工厂类
4. Spring 依赖关系
5. LOC理论推导
Bean注入总结:
6. 配置依赖注入
- 新建好一个类.
- 配置bean.xml 和set参数
- 获取ApplicationContext
- 通过ApplicationContext.getBean 方法来获取 类实例
7. 注解配置
1)@Component
可以使用此注解描述 Spring 中的 Bean,但它是一个泛化的概念,仅仅表示一个组件(Bean),并且可以作用在任何层次。使用时只需将该注解标注在相应类上即可。
2)@Repository
用于将数据访问层(DAO层)的类标识为 Spring 中的 Bean,其功能与 @Component 相同。
3)@Service
通常作用在业务层(Service 层),用于将业务层的类标识为 Spring 中的 Bean,其功能与 @Component 相同。
4)@Controller
通常作用在控制层(如 Struts2 的 Action),用于将控制层的类标识为 Spring 中的 Bean,其功能与 @Component 相同。
5)@Autowired
用于对 Bean 的属性变量、属性的 Set 方法及构造函数进行标注,配合对应的注解处理器完成 Bean 的自动配置工作。默认按照 Bean 的类型进行装配。
6)@Resource
其作用与 Autowired 一样。其区别在于 @Autowired 默认按照 Bean 类型装配,而 @Resource 默认按照 Bean 实例名称进行装配。
@Resource 中有两个重要属性:name 和 type。
Spring 将 name 属性解析为 Bean 实例名称,type 属性解析为 Bean 实例类型。如果指定 name 属性,则按实例名称进行装配;如果指定 type 属性,则按 Bean 类型进行装配。
如果都不指定,则先按 Bean 实例名称装配,如果不能匹配,则再按照 Bean 类型进行装配;如果都无法匹配,则抛出 NoSuchBeanDefinitionException 异常。
7)@Qualifier
与 @Autowired 注解配合使用,会将默认的按 Bean 类型装配修改为按 Bean 的实例名称装配,Bean 的实例名称由 @Qualifier 注解的参数指定。
- 配置beans.xml 自动扫描
- 打上注解
- 通过getBeans 反射获取类
8. 属性自动装配
@AutoWrite 根据属性类型自动进行装配
自动装配就是指 Spring 容器可以自动装配(autowire)相互协作的 Bean 之间的关联关系,将一个 Bean 注入其他 Bean 的 Property 中。
- 新建DAO和impl实现类
- services中用到这个类
- 测试,调用一下 userServices.add() 方法来测试
9. 完全的基于注解开发
现在我们还是用到了spring-context.xml的配置文件,基于注解以后这以后可以省略。
1. 新建类,打上配置的注解
2. 基于类反射获取loc容器
9. 代理设计模式
比如我想见到马云,给他还100快花呗。但是我又找不到他。
这个时候,就有一个还款平台(代理),通过还钱给它,它替我还钱给花呗。
10. AOP 面向切面编程
-
- AOP 的全称是“Aspect Oriented Programming”,即面向切面编程,它将业务逻辑的各个部分进行隔离,使开发人员在编写业务逻辑时可以专心于核心业务,从而提高了开发效率。
- AOP 采取横向抽取机制,取代了传统纵向继承体系的重复性代码,其应用主要体现在事务处理、日志管理、权限控制、异常处理等方面。
- 目前最流行的 AOP 框架有两个,分别为 Spring AOP 和 AspectJ。
11. Spring JDK动态代理
1. 创建DAO,提供增删查改方法
1. 实现impl,并实现增删查改方法
3. 创建切面类
4. 创建代理类
5. 测试代理类
12. CGLIB 代理
- jdk动态代理的有点是简单,缺点是必须要有interface
- 所以这里可以用CGLIB来生成代理类
代理结构和之前差不多
- 准备目标类(可以不需要interface)
- 准备切面实例
- 创建Enhancer 代理
- 设置增强类(设置被代理的类)
- 设置毁掉方法,类似JDK动态代理 的newProxyInstance 方法
- 生成新的代理
13. Aspectj 代理
- 配置pom.xml 增加aspectj,spring-aspects,aspectjtools,aopalliance,aspectjweaver,spring-aop 等包。
- 新建Bean类 并打上注解
- 新建Proxy 类,并声明,前置/后置等方法,并打上注解
- 配置beans.xml 开启自动扫描。
- 最后执行方法
14. JDBCTemplate
- 安装JDBC和Spring 相关包。
- 编写DAO。
- 编写DAOImpl 实现 和 增加类属性 jdbcTemplate,Jdbc 打注解 @AutoWrite.
- 在Pom 文件中增加相关配置,Jdbc的bean和数据库连接
15. Spring事务
1. 脏读
解决办法:把数据库的事务隔离级别调整到READ_COMMITTED(读提交/不可重复读)
2. 不可重复读
解决办法:把数据库的事务隔离级别调整到REPEATABLE_READ(可重复读)
3. 虚读(幻读)
解决办法:把数据库的事务隔离级别调整到SERIALIZABLE_READ(序列化执行),或者数据库使用者自己进行加锁来保证。
不可重复读出现多是因为修改;幻读重点是新增、删除。mysql中的REPEATABLE_READ模式引入了间隙锁(GAP),解决了幻读的问题。不论是什么方式解决幻读,都会付出一定代价的性能让步。所以说在业务需求和技术方案之间权衡也是技术人员最需要掌握得技能之一。
16. 转账事务控制示例
- 引入相关包
- 配置pom.xml,头声明,声明式开启事务,开启事务注解
<?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-4.3.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.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-4.3.xsd
-->
<!--jdbc链接-->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
<property name="url" value="jdbc:mysql://localhost:3306/book"></property>
<property name="username" value="root"></property>
<property name="password" value="root"></property>
</bean>
<!--配置jdbcTemplate-->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!--开启事务-->
<bean id="transitionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!--开启事务注解-->
<tx:annotation-driven transaction-manager="transitionManager"></tx:annotation-driven>
<!--开启注解-->
<context:component-scan base-package="com.liyong"></context:component-scan>
<!--开启自动扫描-->
<aop:aspectj-autoproxy proxy-target-class="true"/>
</beans>
- 新建DAO,DAOImpl 实现,Services ,ServicesImpl实现。
- 注解事务,并设置隔离级别。
- 测试
转帐前 每个人都是 2000
这里设置了错误,来让事务生效,如果出错,则应该 rollback,如果出现 4000 和 0 的话,就是事务不生效。
转账后
可以看到,转账没有生效。已经回滚了。
17. 事务不生效的一些原因。
在配置jdbc后程序就可以正常运行了,但是如果事务没有配置生效的话,程序依旧能跑。这里有一些常见问题,可以用来排查。
- mysql 不是innoDb 引擎。 解决办法,设置为innoDb.
- pom 头和bean没有配置,此时不会报错,事务也不会生效。