Spring
一,Spring框架是什么
- Spring是一个轻量级的控制反转(IoC)和面向切面(AOP)的容器框架
- 2004年诞生,也叫Spring Framework,开源框架
- 降低Java开发复杂度,解决业务逻辑层和其它层耦合的问题
- 如何降低复杂度和实现解耦
- 基于POJO轻量级和最小浸入性编程
- 通过依赖注入和面向切面实现解耦
- 基于切面和惯例进行声明式编程
- 通过切面和模板减少样板式代码
- 如何降低复杂度和实现解耦
- 提供了一个底层容器和基础设施,可以和其他开源框架无缝集成
- 其他版本介绍
- SpringBoot
- 快速开发脚手架
- 基于SpringBoot可以开发单个微服务(小模块)
- 约定大于配置
- SpringCloud
- 基于SpringBoot实现
- 微服务整合
- 学习上面需要掌握Spring,SpringMVC
- SpringBoot
二,优缺点
- 优点
- 方便解耦,将所有对象的创建和依赖关系的维护交给Spring
- AOP,支持面向切面编程
- 支持声明式事务
- 支持Junit,注解测试
- 扩展性强,便于整合其它框架
- 封装Java API,简化API使用
- 强大的向后兼容(可以用最新的版本)
- 易用性强
- 缺点
- Spring 大而全,不够精简
- Spring 依赖反射,反射影响性能
- 使用门槛高,学习有难度(配置繁琐)
三,组成部分和学习要点
- 组成和功能
- [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iJu9C00J-1636367556365)(D:\ycdl\JavaNote\笔记\img\Spring2.png)]
- Spring Core: 基础,可以说 Spring 其他所有的功能都需要依赖于该类库。主要提供 IoC 依赖注入功能。
- Spring Aspects : 该模块为与AspectJ的集成提供支持。
- Spring AOP :提供了面向切面的编程实现。
- Spring JDBC : Java数据库连接。
- Spring JMS :Java消息服务。
- Spring ORM : 用于支持Hibernate等ORM工具。
- Spring Web : 为创建Web应用程序提供支持。
- Spring Test : 提供了对 JUnit 和 TestNG 测试的支持。
- 依赖关系
- [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XP6oImAz-1636367556372)(D:\ycdl\JavaNote\笔记\img\Spring.png)]
- 各个部件的介绍
- 学习要点
- IOC 控制反转 (重点)
- AOP 面向切面编程 (重点)
- 访问数据库
- web应用
- 集成外部组件
四,配置Spring开发环境
1. 首先需要下载Spring Framework
-
去找Spring官网
-
点击Projects 找到Spring Framework
-
maven坐标(如果用最大的,maven会将其他依赖都下载)
-
<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>5.3.5</version> </dependency> <!-- https://mvnrepository.com/artifact/org.springframework/spring-jdbc --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>5.3.5</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.11</version> <scope>test</scope> </dependency>
-
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7tEjPmjr-1636367556374)(D:\ycdl\JavaNote\笔记\img\Spring3.png)]
-
2.写实现
-
dao层
-
package com.itcase.dao.impl; import com.itcase.dao.UserDao; public class mysqlImpl implements UserDao { public void save() { System.out.println("mysql start save...."); } }
-
package com.itcase.dao.impl; import com.itcase.dao.UserDao; public class oracleImpl implements UserDao { public void save() { System.out.println("oracle save......"); } }
-
service层
-
package com.itcase.service.impl; import com.itcase.dao.UserDao; import com.itcase.service.UserService; public class UserServiceImpl implements UserService { private UserDao userDao; //set 方法注入UserDao public void setUserDao(UserDao userDao){ this.userDao = userDao; } public void save(){ userDao.save(); } }
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"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- id 随便起-->
<bean id="userDao" class="com.itcase.dao.impl.mysqlImpl"></bean>
<bean id="oracleImpl" class="com.itcase.dao.impl.oracleImpl"></bean>
<!-- name如果set方法注入(setUserDao) 则是方法名(userDao) -->
<bean id="userService" class="com.itcase.service.impl.UserServiceImpl">
<property name="userDao" ref="userDao"></property>
</bean>
</beans>
4.测试环境
@Test
public void test01(){
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("Application-config.xml");
UserService service = (UserService) context.getBean("userService");
service.save();
}
五. 学习要点展开
1. IOC是什么
-
情景 :需求改变必须改代码,接口实现增加,修改成本十分高,可扩展性差
-
private userDao userDao; public void setUserDao(UserDao userDao){ this.userDao = userDao; }
-
实现将对象的创建权交给使用者
-
(对象可以自己创建,同样可以使用Spring的IOC,让Spring容器创建对象)控制反转
-
降低了耦合(DI(依赖注入)实现)
-
实现方式
- XML
- 注解
- 自动装配
2.Spring配置文件
-
Bean
id
Bean
的唯一标识class
全限定类名
-
alias
别名 -
<alias name="userDao" alias="dao"></alias>
-
name
- 作为别名 可以同时取多个别名
,
空格;
可作为分隔符
-
import
一般用于团队开发使用 可以将多个配置文件导入合并
3.依赖注入
-
构造器注入
<constructor-arg name="username" value="admin"></constructor-arg>
- 特别注意 如果存在有参构造请必须写无参构造,否则编译期报错
-
set方法注入(重点)
- 具体实现 参见Spring环境配置
- 依赖:
Bean
对象依赖于容器 - 注入:
Bean
对象的所有属性,由Spring
容器注入
-
其他方式
-
<bean id="address" class="com.itCase.pojo.Address"> <property name="address" value="北京市朝阳区"/> </bean> <bean id="user" class="com.itCase.pojo.User"> <!-- 常量注入--> <property name="name" value="小明"/> <!-- 对象注入--> <property name="address" ref="address"/> <!-- 数组--> <property name="books"> <array> <value>西游记</value> <value>红楼梦</value> <value>水浒传</value> </array> </property> <!-- list注入--> <property name="hobby"> <list> <value>打篮球</value> <value>打游戏</value> <value>游山玩水</value> </list> </property> <!-- Map--> <property name="card"> <map> <entry key="身份证" value="531222200008183723"/> <entry key="学生卡" value="P191713256"/> <entry key="银行卡" value="6213222000158686"/> </map> </property> <!-- set--> <property name="game"> <set> <value>LOL</value> <value>BOB</value> <value>COC</value> </set> </property> <!-- null--> <property name="married"> <null/> </property> <!-- 空字符--> <!-- <property name="married" value=""/>--> <!-- properties--> <property name="info"> <props> <prop key="序号">1</prop> <prop key="学号">P191713256</prop> <prop key="性别">男</prop> <prop key="成绩">A</prop> </props> </property> </bean>
-
命名空间注入
-
<?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:p="http://www.springframework.org/schema/p" xmlns:c="http://www.springframework.org/schema/c" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <!-- xmlns:p="http://www.springframework.org/schema/p" --> <!-- p 命名空间注入 对应set注入--> <bean id="userInfo" class="com.itCase.pojo.UserInfo" p:name="小红" p:age="18"/> <bean id="user" class="com.itCase.pojo.User" p:address-ref="address"/> <!-- c 命名空间就是构造器注入--> <!-- <bean id="address" class="com.itCase.pojo.Address" p:address="小明"/>--> <bean id="address" class="com.itCase.pojo.Address" c:address="西安未央"/> </beans>
-
作用相同的写法
UserInfo bean = context.getBean("userInfo",UserInfo.class);
UserInfo bean = (UserInfo)context.getBean("userInfo");
-
Bean
的作用域-
默认是单例的
-
<bean id="address" class="com.itCase.pojo.Address" c:address="西安未央" scope="prototype"/>
1、singleton:只要id与该bean定义相匹配,则只会返回bean的同一实例。注意:Singleton作用域是Spring中的缺省作用域
**2、prototype:**每次
getBean()
都会给出一个新的实例web中的:
**2、request:**在一次HTTP请求中,一个bean定义对应一个实例;即每次HTTP请求将会有各自的bean实例, 它们依据某个bean定义创建而成。该作用域仅在基于web的Spring ApplicationContext情形下有效。
考虑下面bean定义:针对每次HTTP请求,Spring容器会根据loginAction bean定义创建一个全新的LoginAction bean实例, 且该loginAction bean实例仅在当前HTTP request内有效,因此可以根据需要放心的更改所建实例的内部状态, 而其他请求中根据loginAction bean定义创建的实例,将不会看到这些特定于某个请求的状态变化。 当处理请求结束,request作用域的bean实例将被销毁。
**4、session:**在一个HTTP Session中,一个bean定义对应一个实例。该作用域仅在基于web的Spring ApplicationContext情形下有效。
考虑下面bean定义:针对某个HTTP Session,Spring容器会根据userPreferences bean定义创建一个全新的userPreferences bean实例, 且该userPreferences bean仅在当前HTTP Session内有效。 与request作用域一样,你可以根据需要放心的更改所创建实例的内部状态,而别的HTTP Session中根据userPreferences创建的实例, 将不会看到这些特定于某个HTTP Session的状态变化。 当HTTP Session最终被废弃的时候,在该HTTP Session作用域内的bean也会被废弃掉。
**5、global session:**在一个全局的HTTP Session中,一个bean定义对应一个实例。典型情况下,仅在使用portlet context的时候有效。该作用域仅在基于web的Spring ApplicationContext情形下有效。
考虑下面bean定义:global session作用域类似于标准的HTTP Session作用域,不过它仅仅在基于portlet的web应用中才有意义。Portlet规范定义了全局Session的概念,它被所有构成某个portlet web应用的各种不同的portlet所共享。在global session作用域中定义的bean被限定于全局portlet Session的生命周期范围内。
请注意:假如你在编写一个标准的基于Servlet的web应用,并且定义了一个或多个具有global session作用域的bean,系统会使用标准的HTTP Session作用域,并且不会引起任何错误。
-
-
4.自动装配
-
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" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="cat" class="com.itCase.pojo.Cat"/> <bean id="Dog" class="com.itCase.pojo.Dog"/> <bean id="People" class="com.itCase.pojo.People"> <property name="name" value="小米"/> <property name="cat" ref="cat"/> <property name="dog" ref="Dog"/> </bean> </beans>
-
autowire
-
根据set方法后面的名字寻找(注意必须是首字母小写不然报错)
<bean id="People" class="com.itCase.pojo.People" autowire="byName"> <property name="name" value="小米"/> </bean>
-
byType
-
根据Bean的类型,不过必须全局唯一(单例)
-
-
Java 注解
-
注解比较推荐,
jdk1.5
后支持 -
注解使用
-
导入约束
-
<?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: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/context http://www.springframework.org/schema/context/spring-context.xsd"> </beans>
-
配置支持
-
<context:annotation-config/>
-
-
@Autowired
-
@Autowired private Cat cat; @Autowired private Dog dog;
-
@Qualifier(value="dog")
- 当有多个实例时指定一个实例
@Resource
根据类型匹配
-
注解可以不用set
-
注意:
@nullTable
允许 null
-
-
隐式的自动装配重要
5.注解开发(推荐且重要)
在Spring 4
之后使用注解必须导入 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: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/context http://www.springframework.org/schema/context/spring-context.xsd"> <!-- 组件扫描 扫描包下类的注解--> <context:component-scan base-package="com.itCase.pojo"/> <!-- 注解生效--> <context:annotation-config/> </beans>
-
-
Bean
@Component("UserPojo")
表明被Spring管理,- 与
<bean id="user" class="com.itCase.pojo.UserInfo"></bean>
作用一致
-
属性注入
-
@Value("Tom") private String name; @Value("1") private Integer id;
-
衍生注解
- 根MVC来标注
@Component
的扩展- dao
@Repository
- service
@Service
- Controller
@Controller
- 注意 不能上面标识重名
- dao
-
作用域
@Scope("prototype")
-
xml最佳实践
- xml适用于所有的场合
- 注解 不是自己的类使用不了,维护复杂
- xml 管理Bean
- 注解 属性注入
- 注意 让注解生效
-
完全注解配置
-
Spring 4 SpringBoot 中使用,建议注解
-
使用步骤
-
搭建MVC层接口与实现类
-
使用
config.java
(Spring 核心配置类) 替代原有的Application-config.xml
-
//表明这个类被Spring管理 @Configuration //组件扫描 @ComponentScan("com.itCase") public class MyConfig { //非自定义的类 @Bean("user") @Scope("prototype") public User getUser(){ return new User(); } //Bean的初始化方法 @PostConstruct public void init(){ System.out.println("初始化开始了"); } //Bean的销毁方法 @PreDestroy public void destroy(){ System.out.println("Bean被销毁了"); } }
-
使用注解将接口实现类放进Spring容器
-
web
@Controller("userController")
-
dao
@Repository("userDao")
-
service
-
//使用注解 将本类放入容器 @Service("userService") public class UserServiceImpl implements UserService { private UserDao userDao; //如果用这@Service("userService") //就不能@Autowired @Qualifier("userDao") 变量注入 只构造和set注入 @Autowired @Qualifier("userDao") public void setUserDao(UserDao userDao){ this.userDao = userDao; } // public UserServiceImpl(){ // // } // @Autowired // public UserServiceImpl(UserDao userDao){ // this.userDao = userDao; // } public void save(){ userDao.save(); } }
-
-
需要注意的是
-
重要 自定义的类可以用上面的注解或者
@Component("UserPojo")
表明被Spring管理 -
非自定义的类 则需要
Bean
标签实现注入Spring容器 -
特别注意的遗留问题
-
@Service("userService")
使用此类标签 -
//如果用这@Service("userService") //就不能@Autowired @Qualifier("userDao") 变量注入 只构造和set注入 @Autowired @Qualifier("userDao")
-
-
-
外部资源的引入
-
XML文件引入
-
<context:property-placeholder location="classpath:Druid.properties"/> <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"> <property name="driverClassName" value="${jdbc.driverClassName}"></property> <property name="url" value="${jdbc.url}"></property> <property name="username" value="${jdbc.username}"></property> <property name="password" value="${jdbc.password}"></property> </bean>
-
Java注解引入
-
// 加载配置文件<context:property-placeholder location="classpath:Druid.properties"/> @PropertySource("classpath:Druid.properties") public class dataSource { //不同于xml //外部资源的引入的表达式 不能直接写需要注入 @Value("${jdbc.driverClassName}") private String driver; @Value("${jdbc.url}") private String url; @Value("${jdbc.username}") private String username; @Value("${jdbc.password}") private String password; @Bean("data") public DruidDataSource getDataSource() { DruidDataSource data = new DruidDataSource(); data.setDriverClassName(driver); data.setUrl(url); data.setUsername(username); data.setPassword(password); return data; } }
-
-
-
6. AOP 代理模式
- 静态代理
- 加东西会写很多类
- 动态代理
- 重要底层都是反射
- 分类
- 基于接口的(JDK动态代理)
- 基于类的(cglib)
- java (.class)
- 关键类
- Poxy , InvocationHandler
- 重要方法invoke()
3.动态代理如何实现
- 代理类实现
package com.itCase02;
import org.omg.CORBA.OBJ_ADAPTER;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* 动态生成代理类
*/
public class ProxyInvocationHandler implements InvocationHandler {
//获取要创建的类型
private Object target;
public void setTarget(Object target) {
this.target = target;
}
//生成代理类对象
public Object getProxy(){
return Proxy.newProxyInstance(ProxyInvocationHandler.class.getClassLoader(),
target.getClass().getInterfaces(),this);
}
//处理代理实例
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
logStart(method.getName());
Object invoke = method.invoke(target, args);
logFinish(method.getName());
return invoke;
}
//需要增强的功能
public void logStart(String msg){
System.out.println("[DEBUG]:---执行了"+msg+"方法---");
}
public void logFinish(String msg){
System.out.println("[DEBUG]:-执行了"+msg+"方法完成--");
}
}
-
test
@Test public void daoTest02(){ UserDao userDao = new UserDaoImpl(); ProxyInvocationHandler handler = new ProxyInvocationHandler(); handler.setTarget(userDao); UserDao proxy = (UserDao) handler.getProxy(); proxy.add(); proxy.query(); proxy.delete(); proxy.upData(); }
7,AOP
-
AOP Spring是什么有什么作用
在软件业,AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方
式和运行期动态代理实现程序功能的统一维护的一种技术。AOP是OOP的延续,是软件开发中的一个
热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。利用AOP可以对业务逻辑
的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高
了开发的效率。-
AOP编程可不是Spring独有的,Spring只是支持AOP编程的框架之一,这一点非常重要,切勿搞反了关系
-
AOP分两类
- 一类可以对方法的参数进行拦截,
- 一类是对方法进行拦截,SpringAOP属于后者,所以Spring的AOP是属于方法级的
-
AOP作用
- 声明式事务
- 自定义切面
-
相关概念
Aspect(切面): Aspect 声明类似于 Java 中的类声明,在 Aspect 中会包含着一些 Pointcut 以及相应的 Advice。
Joint point(连接点):表示在程序中明确定义的点,典型的包括方法调用,对类成员的访问以及异常处理程序块的执行等等,它自身还可以嵌套其它 joint point。
Pointcut(切点):表示一组 joint point,这些 joint point 或是通过逻辑关系组合起来,或是通过通配、正则表达式等方式集中起来,它定义了相应的 Advice 将要发生的地方。
Advice(增强):Advice 定义了在 Pointcut 里面定义的程序点具体要做的操作,它通过 before、after 和 around 来区别是在每个 joint point 之前、之后还是代替执行的代码。
Target(目标对象):织入 Advice 的目标对象.。
Weaving(织入):将 Aspect 和其他对象连接起来, 并创建 Adviced object 的过程
-
-
Spring AOP 配置环境
-
Spring AOP 所需依赖
-
<dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.8.7</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>5.2.13.RELEASE</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <scope>test</scope> </dependency>
-
导入命名空间
-
xmlns:aop="http://www.springframework.org/schema/aop" http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
-
实现方式
-
第一种
-
public class AfterLog implements AfterReturningAdvice { //returnValue 返回值 @Override public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable { System.out.println("[DEBUG]->"+target.getClass().getName()+"->"+method.getName()+"执行了返回了->"+returnValue); } }
-
public class log implements MethodBeforeAdvice { /* * Method 方法 * Object[] 参数 * Object target 目标对象 * */ @Override public void before(Method method, Object[] args, Object target) throws Throwable { System.out.println("[DEBUG]->"+target.getClass().getName()+"的"+method.getName()+"执行了"); } }
-
<bean id="userDao" class="com.itDuck.dao.impl.UserDaoImpl"/> <bean id="log" class="com.itDuck.log.log"/> <bean id="logAfter" class="com.itDuck.log.AfterLog"/> <!--aop第一种方式 配置 aop 命名空间 导入约束--> <aop:config> <!-- 定义切点 --> <aop:pointcut id="pointcut" expression="execution(* com.itDuck.dao.impl.UserDaoImpl.*(..))"/> 通知: 即方法 <aop:advisor advice-ref="log" pointcut-ref="pointcut"/> <aop:advisor advice-ref="logAfter" pointcut-ref="pointcut"/> </aop:config>
-
test
-
@Test public void UserDaoAddTest(){ ApplicationContext context = new ClassPathXmlApplicationContext("Application-config.xml"); UserDao dao = context.getBean("userDao",UserDao.class); dao.add(); dao.upData(); dao.delete(); dao.query(); }
-
第二种 不实现接口自定义类
-
public class Pointcut { public void start(){ System.out.println("------启动-------"); } public void finish(){ System.out.println("--------完成----------"); } }
-
<bean id="diy" class="com.itDuck.diy.Pointcut"/> <aop:config> <!-- 自定义切面--> <aop:aspect ref="diy"> <!-- 切入点:--> <aop:pointcut id="pointcut" expression="execution(* com.itDuck.dao.impl.UserDaoImpl.*(..))"/> <!-- 通知: 即方法--> <aop:before method="start" pointcut-ref="pointcut"/> <aop:after method="finish" pointcut-ref="pointcut"/> </aop:aspect> </aop:config>
-
第三种方式 注解实现
-
@Component("APCut") @Aspect public class AnnotationPointCut { @Before("execution(* com.itDuck.dao.impl.UserDaoImpl.*(..))") public void Before(){ System.out.println("------------start-----------"); } @AfterReturning("execution(* com.itDuck.dao.impl.UserDaoImpl.*(..))") public void After(){ System.out.println("-------------end-----------"); } @Around("execution(* com.itDuck.dao.impl.UserDaoImpl.*(..))") public void around(ProceedingJoinPoint jp) throws Throwable { System.out.println("---------环绕前----------"); //日志打印签名 Signature signature = jp.getSignature(); System.out.println(signature); //方法执行 jp.proceed(); System.out.println("---------环绕后----------"); } }
-
-
8.Spring整合MyBatis
-
实现步骤
-
导入maven依赖
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>5.2.13.RELEASE</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <version>5.2.13.RELEASE</version> </dependency> <!-- spring jdbc --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>5.2.13.RELEASE</version> </dependency> <!--Spring事务提交 --> <!-- mybatis--> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.4.5</version> </dependency> <!-- mysql driver--> <!-- 日志--> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.17</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.23</version> </dependency> <!-- 日志--> <!-- druid数据源 --> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.1.23</version> </dependency> <!--Spring-jdbc--> <!-- aop依赖--> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.8.7</version> </dependency> <!--mybatis 整合Spring --> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis-spring</artifactId> <version>2.0.1</version> </dependency> <!-- pojo lombok --> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.12</version> <scope>provided</scope> </dependency>
-
配置让xml被识别
<!--配置识别xml 配置文件--> <resources> <resource> <directory>src/main/java</directory> <includes> <include>**/*.properties</include> <include>**/*.xml</include> </includes> <filtering>true</filtering> </resource> <resource> <directory>src/main/resources</directory> <includes> <include>**/*.properties</include> <include>**/*.xml</include> </includes> <filtering>true</filtering> </resource> </resources>
-
按照搭建mybatis的步骤,调通实现查询
-
主配置文件
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration> <!-- 引入jdbc配置文件--> <properties resource="druid.properties"/> <settings> <setting name="logImpl" value="LOG4J"/> </settings> <typeAliases> <typeAlias type="com.itCast.pojo.UserPojo" alias="user"/> </typeAliases> <!-- <environments default="development">--> <!-- <environment id="development">--> <!-- <transactionManager type="JDBC"/>--> <!-- <dataSource type="POOLED">--> <!-- <property name="driver" value="${driverClassName}"/>--> <!-- <property name="url" value="${jdbc.url}"/>--> <!-- <property name="username" value="${jdbc.username}"/>--> <!-- <property name="password" value="${jdbc.password}"/>--> <!-- </dataSource>--> <!-- </environment>--> <!-- </environments>--> <!-- <mappers>--> <!-- <mapper resource="com/itCast/mapper/UserMapper.xml"/>--> <!-- </mappers>--> </configuration>
-
UserMapper.xml 数据库映射文件
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.itCast.mapper.UserMapper"> <select id="getUserList" resultType="com.itCast.pojo.UserPojo"> select * from user </select> </mapper>
-
特别注意
- 数据源和JDBC配置
druid.properties
问题- url -> jdbc.url
- username -> jdbc.username
- password -> jdbc.password
- 写成左边的话会出现错误:调用系统的用户对象
- 整合Spring时在主配置文件
- 请注释掉mybatis当中与Spring重复的配置否则会报错
- 例如:
environments
和mappers
- 数据源和JDBC配置
-
-
编写配置文件
-
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: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/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"> <!-- 组件扫描 扫描包下类的注解--> <!-- <context:component-scan base-package="com.itCast"/>--> <!-- 注解生效--> <!-- <context:annotation-config/>--> <import resource="classpath:spring-dao.xml"/> <!-- 第一种方式 注册impl--> <bean id="userMapper" class="com.itCast.mapper.impl.UserMapperImpl"> <property name="sqlSessionTemplate" ref="sqlSession"/> </bean> <!-- 第二种方式 不用自己写sqlSessionFactory sqlSession--> <bean id="userMapper02" class="com.itCast.mapper.impl.UserMapper02"> <property name="sqlSessionFactory" ref="sqlSessionFactory"/> </bean> <!-- <aop:aspectj-autoproxy/>--> </beans>
-
Spring-Dao 配置文件
<?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: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/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"> <!-- 引入外部资源--> <context:property-placeholder location="druid.properties"/> <!-- 配置druid数据源 druid.properties--> <!-- 注意 druid.properties 当中username password 写成jdbc.username jdbc.password 不然会报错--> <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"> <property name="driverClassName" value="${driverClassName}"/> <property name="url" value="${jdbc.url}"/> <property name="username" value="${jdbc.username}"/> <property name="password" value="${jdbc.password}"/> </bean> <!-- 注册mybatis所用对象--> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="dataSource"/> <property name="configLocation" value="classpath:mybatis-config.xml"/> <property name="mapperLocations" value="classpath:com/itCast/mapper/UserMapper.xml"/> </bean> <bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate"> <constructor-arg index="0" ref="sqlSessionFactory"/> </bean> </beans>
-
数据源和JDBC配置
driverClassName=com.mysql.jdbc.Driver jdbc.url=jdbc:mysql://localhost:3306/stu_new_manager?characterEncoding=utf8&useSSL=false&serverTimezone=UTC&rewriteBatchedStatements=true jdbc.username=root jdbc.password=123456 initialSize=5 maxActive=10 maxWait=3000 maxIdle=8 minIdle=3
-
日志配置 LOG4J
#将等级为DEBUG的日志信息输出到console和file这两个目的地,console和file的定义在下面的代码 log4j.rootLogger=DEBUG,console,file #控制台输出的相关设置 log4j.appender.console = org.apache.log4j.ConsoleAppender log4j.appender.console.Target = System.out log4j.appender.console.Threshold=DEBUG log4j.appender.console.layout = org.apache.log4j.PatternLayout log4j.appender.console.layout.ConversionPattern=[%c]-%m%n #文件输出的相关设置 log4j.appender.file = org.apache.log4j.RollingFileAppender log4j.appender.file.File=./log/kexing.log log4j.appender.file.MaxFileSize=10mb log4j.appender.file.Threshold=DEBUG log4j.appender.file.layout=org.apache.log4j.PatternLayout log4j.appender.file.layout.ConversionPattern=[%p][%d{yy-MM-dd}][%c]%m%n #日志输出级别 log4j.logger.org.mybatis=DEBUG log4j.logger.java.sql=DEBUG log4j.logger.java.sql.Statement=DEBUG log4j.logger.java.sql.ResultSet=DEBUG log4j.logger.java.sql.PreparedStatement=DEBUG
-
特别注意
-
编写的两个Spring配置文件 ,需要在主配置文件中引入
-
注意整合时Spring 获取SqlSession的两个方式
-
不需要继承
<!-- 注册mybatis所用对象--> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="dataSource"/> <property name="configLocation" value="classpath:mybatis-config.xml"/> <property name="mapperLocations" value="classpath:com/itCast/mapper/UserMapper.xml"/> </bean> <bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate"> <constructor-arg index="0" ref="sqlSessionFactory"/> </bean>
public class UserMapperImpl implements UserMapper { private SqlSessionTemplate sqlSessionTemplate; public void setSqlSessionTemplate(SqlSessionTemplate sqlSessionTemplate) { this.sqlSessionTemplate = sqlSessionTemplate; } @Override public List<User> getUserList() { UserMapper mapper = sqlSessionTemplate.getMapper(UserMapper.class); return mapper.getUserList(); } }
<!-- 第一种方式 注册impl--> <bean id="userMapper" class="com.itCast.mapper.impl.UserMapperImpl"> <property name="sqlSessionTemplate" ref="sqlSession"/> </bean>
-
第二种方式
extends SqlSessionDaoSupport
package com.itCast.mapper.impl; import com.itCast.mapper.UserMapper; import com.itCast.pojo.User; import org.mybatis.spring.support.SqlSessionDaoSupport; import java.util.List; public class UserMapper02 extends SqlSessionDaoSupport implements UserMapper { @Override public List<User> getUserList() { return getSqlSession().getMapper(UserMapper.class).getUserList(); } }
<!-- 第二种方式 不用自己写sqlSession--> <bean id="userMapper02" class="com.itCast.mapper.impl.UserMapper02"> <property name="sqlSessionFactory" ref="sqlSessionFactory"/> </bean>
-
-
配置文件 properties 中命名问题 ,借鉴
按照搭建mybatis的步骤,调通实现查询
->3.特别注意
-
-
-
最后的步骤
-
除去mybatis的实现外还需要编写UserMapper.interface 的实现类
-
public class UserMapper02 extends SqlSessionDaoSupport implements UserMapper { @Override public List<User> getUserList() { return getSqlSession().getMapper(UserMapper.class).getUserList(); } }
-
测试类
-
@Test public void getUserListTest1(){ ApplicationContext context = new ClassPathXmlApplicationContext("Application-config.xml"); UserMapper userMapper = context.getBean("userMapper", UserMapper.class); List<User> list = userMapper.getUserList(); for (User user : list) { System.out.println(user); } }
-
-
9.声明式事务
-
事务解释
- 同一组业务看成一个业务,全部成功或者全部失败
- 开发中十分重要确保完整性和一致性
-
事务的ACID原则
- 原子性
- 一致性
- 隔离性
- 多个事务访问同一资源时,防止数据损坏
- 持久性
- 事务一旦提交,就会被持久保存
-
如何实现
-
配置
<!-- spring aop 配置声明式事务 --> <bean id="transaction" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"/> </bean> <!--结合aop实现事务--> <!-- 配置事务通知--> <tx:advice id="txAction" transaction-manager="transaction"> <tx:attributes> <tx:method name="add" propagation="REQUIRED"/> <tx:method name="delete" propagation="REQUIRED"/> <tx:method name="query" propagation="REQUIRED"/> <tx:method name="*" propagation="REQUIRED"/> </tx:attributes> </tx:advice> <!--aop--> <aop:config> <aop:pointcut id="txPointcut" expression="execution(* com.itCast.mapper.*.*(..))"/> <aop:advisor advice-ref="txAction" pointcut-ref="txPointcut"/> </aop:config>
-