Spring 学习
知识点
-
简介
- Spring依赖包
<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>5.2.5.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>5.2.3.RELEASE</version> </dependency> ```
-
IOC理论
- 控制反转(IOC) 面向切面变成(AOP)
- 传统的MVC模式
- UserDao
- USerDaoImpl
- UserService
- UserServiceImpl
在此之前,用户需求可能会影响原来的代码
在UserServiceImpl里面 设置private UserDao user;
通过使用set,则可以根据用户需求选择,而不用改变原来的代码public void setUserDao(UserDao userDao){ this.userDao = userDao; }
- 之前是主动创建对象,控制权在程序员手上
- 使用set之后,是被动接受对象
-
Hello Spring
- resource中 beans.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 https://www.springframework.org/schema/beans/spring-beans.xsd"> <!--bean = 对象--> <!--id = 变量名--> <!--class = new的对象--> <!--property 相当于给对象中的属性设值--> <bean id="hello" class="com.hou.pojo.Hello"> <property name="name" value="Spring"/> </bean> </beans>
- test中
import com.hou.pojo.Hello; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class Mytest { public static void main(String[] args) { //获取spring上下文对象 ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml"); //我们的对象下能在都在spring·中管理了,我们要使用,直接取出来就可以了 Hello hello = (Hello) context.getBean("hello"); System.out.println(hello.toString()); } }
- 涉及知识点:
- bean = 对象
- id = 变量名
- class = 类
- property 相当于给对象设置属性
- 核心为 set 注入
- UserServerImpl中存在UserDao属性,则这个时候需要使用 ref
<?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 https://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="userdaomysql" class="com.hou.dao.UserDaoMysqlImpl"></bean> <bean id="userServiceImpl" class="com.hou.service.UserServiceImp"> <!--ref引用spring中已经创建很好的对象--> <!--value是一个具体的值--> <property name="userDao" ref="userdaomysql"/> </bean> </beans>
-
IOC创建对象的方式
- 使用无参构造创建对象,默认
- 使用有参构造
-
下标赋值
<?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 https://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="user" class="com.hou.pojo.User"> <constructor-arg index="0" value="hou"/> </bean> </beans>
-
类型赋值
<bean id="user" class="com.hou.pojo.User"> <constructor-arg type="java.lang.String" value="dong"/> </bean>
-
直接通过参数值
<bean id="user" class="com.hou.pojo.User"> <constructor-arg name="name" value="hou"></constructor-arg> </bean>
-
知识点
IOC创建对象的方式,在这里 Spring类似于婚介网站,不管你想不想要,对象都在里面。
-
Spring 配置
-
别名:使用 <alias />
<bean id="user" class="com.hou.pojo.User"> <constructor-arg name="name" value="hou"></constructor-arg> </bean> <alias name="user" alias="user2aaa"/>
-
Bean的配置
- id: bean的id标识符
- class: bean对象所在的类型
- name:别名,可以同时取多个别名
-
import
将多个配置文件,导入合并成一个
<import resource="beans.xml"/>
-
-
DI依赖注入
-
注入方式
构造器注入 一定要有一个无参构造
set方式注入(重点)
- 依赖:bean对象的创建依赖于容器
- 注入: bean对象中的所有属性,由容器来注入
-
常用的数据类型
Student.java
private String name; private Address address; private String[] books; private List<String> hobbies; private Map<String, String> card; private Set<String> game; private Properties infor; private String wife;
Address.java
public class Address { private String address; public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } @Override public String toString() { return "Address{" + "address='" + address + '\'' + '}'; } }
beans.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 https://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="address" class="com.pojo.Address"> <property name="address" value="xian"></property> </bean> <bean id="student" class="com.pojo.Student"> <property name="name" value="hou"/> <property name="address" ref="address"/> <!--数组注入--> <property name="books"> <array> <value>三国</value> <value>西游</value> <value>水浒</value> </array> </property> <!--list--> <property name="hobbies"> <list> <value>eat</value> <value>drink</value> <value>play</value> </list> </property> <property name="card"> <map> <entry key="1" value="12"/> <entry key="2" value="23"/> </map> </property> <property name="game"> <set> <value>wangzhe</value> <value>daota</value> <value>lol</value> </set> </property> <property name="wife"> <null></null> </property> <!--properties--> <property name="infor"> <props> <prop key="id">20200405</prop> <prop key="name">hdk</prop> </props> </property> </bean> </beans>
-
知识点
-
property里的name 对应 Address.java里面的address
<bean id="address" class="com.pojo.Address"> <property name="address" value="xian"></property> </bean> ```
-
<null/>赋值,赋null值,其效果跟 ex.setvalue(null) 效果一样;
注意 “ ”与null的区别[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-90oEPih1-1598271535913)(image/empty_Null_1.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-i01ztWoh-1598271535934)(image/empty_Null_2.png)]
-
-
第三方 p标签 和 c标签
-
bean.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:p="http://www.springframework.org/schema/p" xmlns:c="http://www.springframework.org/schema/c" xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd"> <!--p命名空间注入/set注入--> <bean id="use" class="com.pojo.User" p:name="dong" p:age="10"> </bean> <!--c命名空间/构造器--> <bean id="use2" class="com.pojo.User" c:name="kun" c:age="19"></bean> </beans>
-
知识点
- p命名空间是使用 set注入
- c命名空间是使用 构造器
-
-
bean的作用域
-
单例模式(默认)不管id有多少个,只要class是一样的,都只有一个对象
<bean id="use2" class="com.pojo.User" c:name="kun" c:age="19" scope="singleton"></bean>
-
原型模式:每次从容器中get的时候,都产生一个新对象
<bean id="use2" class="com.pojo.User" c:name="kun" c:age="19" scope="prototype"></bean>
-
其余的request,session,application这些只能在web开放中使用。
-
-
-
Bean的自动装配
-
Spring有三种装配方式
- 在xml中显示配置
- 在java中显示配置
- 隐式的自动装配bean【important】
-
环境搭建:一个人有两个宠物
-
Byname自动装配:byname会自动查找,和自己对象set对应的值对应的id,保证所有
id唯一,并且和set注入的值一致。-
看例子
<bean id="cat" class="pojo.Cat"/> <bean id = "dog" class="pojo.Dog"/> <!--byname自动查找,和自己对象set对应的值对应的id--> <bean id="people" class="pojo.People" autowire="byName"> <property name="name" value="sha"></property> </bean>
test code:
people.getCat().shout();
-
而如果是将id改了,即id=“cat123”,则查找不到
<bean id="cat123" class="pojo.Cat"/> <bean id = "dog" class="pojo.Dog"/> <!--byname自动查找,和自己对象set对应的值对应的id--> <bean id="people" class="pojo.People" autowire="byName"> <property name="name" value="sha"></property> </bean>
-
以前的话,需要使用ref
<bean id="userdaomysql" class="com.hou.dao.UserDaoMysqlImpl"></bean> <bean id="userServiceImpl" class="com.hou.service.UserServiceImp"> <!--ref引用spring中已经创建很好的对象--> <!--value是一个具体的值--> <property name="userDao" ref="userdaomysql"/> </bean>
-
-
Bytype 自动装配:bytype会自动查找,和自己对象属性相同的bean,保证所有的class唯一。
- 跟byname差不多,直接看代码
<?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 https://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="cat11" class="com.pojo.Cat"/> <bean id="dog" class="com.pojo.Dog"/> <!--byname会自动查找,和自己对象set对应的值对应的id--> <!--<bean id="people" class="com.pojo.People" autowire="byName">--> <!--<property name="name" value="hou"></property>--> <!--</bean>--> <!--byType会自动查找,和自己对象属性相同的bean--> <bean id="people" class="com.pojo.People" autowire="byType"> <property name="name" value="hou"></property> </bean> </beans>
- 跟byname差不多,直接看代码
-
-
使用注解自动装配
-
jdk1.5支持的注解,spring2.5支持的注解
-
导入context约束
<?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 https://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd"> <context:annotation-config/> </beans>
-
@Autowire
在属性上使用,也可以在set上使用
可以不用编写set方法了
public class People { @Autowired private Cat cat; @Autowired private Dog dog; private String name; }
@Nullable 字段标志的注解,说明这个字段可以为null
-
-
如果@Autowired自动装配环境比较复杂。自动装配无法通过一个注解完成的时候
我们可以使用@Qualifier(value = “dog”)去配合使用,指定一个唯一的id对象
(也就是说,如果自动装配没有找到相应的id,则使用@Qualifier给的默认值)
public class People { @Autowired private Cat cat; @Autowired @Qualifier(value = "dog") private Dog dog; private String name; }
当然,@Resource(name=“dog”)也可以
区别:
- @autowire通过byType实现,而且必须要求这个对象存在
- @resource默认通过byName实现,如果找不到,通过byType实现
-
-
使用注解开发
-
spring4之后,必须保证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 https://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd"> <context:annotation-config/> </beans>
-
属性注入
@Component public class User { @Value("dong") private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } }
-
衍生的注解
@Component有几个衍生注解,会按照web开发中,mvc架构中分层。
- dao (@Repository)
- service(@Service)
- controller(@Controller)
这四个注解功能一样的,都是代表将某个类注册到容器中
-
作用域
@Scope(“singleton”) @Scope(“prototype”)
-
小结
xml与注解
- xml更加万能,维护简单
- 注解,不是自己的类,使用不了,维护复杂
最佳实践:
- xml用来管理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:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd"> <context:annotation-config/> <!--指定要扫描的包--> <context:component-scan base-package="com.pojo"/> </beans>
-
-
使用Java方式配置spring
- 测试
-
首先编写一个实体类,User
@Component public class User { //注解Value赋值 @Value("Sha") private String name;
-
新建一个config配置包,编写一个MyConfig配置类
@Configuration //代表这是一个配置类 @ComponentScan("pojo") public class MyConfig { @Bean //通过方法注册一个bean,这里的返回值就是Bean类型,方法名就是bean的id public User getUser(){ return new User(); } //上面就相当于: // <beans> // <bean id="getUser" class="pojo.User"/> // </beans> }
-
测试
public void test1(){ //注意这里得使用注解 ApplicationContext ctx = new AnnotationConfigApplicationContext(MyConfig.class); User user = ctx.getBean("getUser",User.class); System.out.println(user); }
-
导入其他配制
如果我们在编写一个配置类:
@Configuration public class MyConfig2{}
现在要在之前的配置类中导入新的配置类,用Import
@Configuration //代表这是一个配置类 @ComponentScan("pojo") @Import(MyConfig2.class) public class MyConfig { @Bean //通过方法注册一个bean,这里的返回值就是Bean类型,方法名就是bean的id public User getUser(){ return new User(); } //上面就相当于: // <beans> // <bean id="getUser" class="pojo.User"/> // </beans> }
-
- 测试
-
代理模式
-
代理可分为静态代理和动态代理
-
代理模式:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-G3RkMNSm-1598271535935)(image/代理模式.png)] -
小实例(以租房为例)
- 抽象角色:类似于 真实角色与代理角色之间 共同的行为
//抽象角色:租房 public interface Rent { public void rent(); }
- 真实角色:
//真实角色:房东,房东要租房子 public class Host implements Rent { public void rent() { System.out.println("房屋出租"); } }
- 代理角色
//代理角色:中介 public class Proxy implements Rent { private Host host; public Proxy(Host host) { this.host = host; } //租房 //中介可以干房东干不了的事 public void rent() { seeHouse(); host.rent(); fare(); } //看房 public void seeHouse(){ System.out.println("带房客看房"); } //收中介费 public void fare(){ System.out.println("收中介费"); } }
- 客户
//客户 public class Client { public static void main(String[] args){ //真实对象必须要实例化 Host host = new Host(); //中介帮助房东 Proxy proxy = new Proxy(host); //你去找中介租房 proxy.rent(); } }
- 抽象角色:类似于 真实角色与代理角色之间 共同的行为
-
AOP的核心就是思想就是:在不改变原有代码的情况下,实现了对原有功能的增强
-
动态代理
- 动态代理的角色跟静态是一样的
- 动态代理的代理类是动态生成的,静态代理的代理类是提前写好的
- 动态代理分成两类:一类是基于接口动态代理,一类是基于类的动态代理
- 基于接口的动态代理----JDK动态代理
- 基于类的动态代理----cglib
- 现在用的较多的是 javasist来生成动态代理。
-
下面给出jdk的动态代理
-
这里需要两个类: Proxy InvocationHandler
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9DhnQb78-1598271535937)(image/invocation.png)][外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cCAJ9UVr-1598271535939)(image/invoke.png)]
-
例程
//这个类 会自动生成代理类 public class ProxyInvocation implements InvocationHandler { //被代理的接口 private Rent rent; public void setRent(Rent rent) { this.rent = rent; } //生成代理类,重点是第二个参数,获取要代理的抽象角色! public Object getProxy(){ System.out.println("输出代理类的参数"); System.out.println(this.getClass().getClassLoader()); System.out.println(rent.getClass().getInterfaces()); return Proxy.newProxyInstance(this.getClass().getClassLoader(),rent.getClass().getInterfaces(),this); } //处理代理实例上的方法调用,并返回结果 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { //添加别的参数 seeHouse(); //核心是通过反射实现的 Object result = method.invoke(rent,args); fare(); return result; } public void seeHouse(){ System.out.println("看房子"); } public void fare(){ System.out.println("收取中介费"); } }
- Rent.java
//抽象角色:租房 public interface Rent { public void rent(); }
- Host.java
//真实角色:房东,房东要租房子 public class Host implements Rent { public void rent() { System.out.println("房屋出租"); } }
- Client
//动态代理 public void test1(){ //真实角色 Rent host1 = new Host(); //代理角色 ProxyInvocation proxyInvocation = new ProxyInvocation(); //通过调用程序处理角色来处理我们调用的接口对象 proxyInvocation.setRent(host1); Rent proxy = (Rent) proxyInvocation.getProxy(); proxy.rent(); }
-
-
一个动态代理可以代理多个类,因为代理的是接口
-
-
AOP
-
导入依赖:
<dependencies> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.9.4</version> </dependency> </dependencies>
-
第一种方式:通过Spring API实现
- 首先编写业务接口和实现类
public interface UserService { public void add(); public void delete(); public void query(); public void update(); }
public class UserServiceImpl implements UserService{ public void add() { System.out.println("add"); } public void delete() { System.out.println("delete"); } public void query() { System.out.println("query"); } public void update() { System.out.println("update"); } }
- 写增强类,一个前置增强 一个后置增强
//增强类 前置增强 public class Log implements MethodBeforeAdvice { //method:要执行的目标对象的方法 //objects:被调用的方法的参数 //o:目标对象 public void before(Method method, Object[] objects, Object o) throws Throwable { System.out.println(o.getClass().getName()+"的"+method.getName()+"方法被执行了"); } }
//增强类 前置增强 public class Log implements MethodBeforeAdvice { //method:要执行的目标对象的方法 //objects:被调用的方法的参数 //o:目标对象 public void before(Method method, Object[] objects, Object o) throws Throwable { System.out.println(o.getClass().getName()+"的"+method.getName()+"方法被执行了"); } }
- 去spring的文件中注册,并实现aop切入实现,注意导入约束 spring-dao.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" 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 "> <!--注册bean--> <bean id="userservice" class="demo1.pojo.UserServiceImpl"/> <bean id="log" class="demo1.pojo.Log"/> <bean id="afterlog" class="demo1.pojo.AfterLog"/> <!--配置aop--> <aop:config> <!--切入点:expression:表达式,execution(要执行的位置)--> <aop:pointcut id="point" expression="execution(* demo1.pojo.UserServiceImpl.*(..))"/> <!--执行环绕--> <aop:advisor advice-ref="log" pointcut-ref="point"/> <aop:advisor advice-ref="afterlog" pointcut-ref="point"/> </aop:config>
- test
@Test public void test1(){ ApplicationContext context = new ClassPathXmlApplicationContext("spring-dao.xml"); UserService userService = context.getBean("userservice", UserService.class); userService.add(); } //结果
- 首先编写业务接口和实现类
-
第二种方式 自定义类实现AOP,目标业务类不变,依旧还是userServiceImpl
- 写我们自己的一个切入类
//第二种方法:自定义类实现Aop public class DiyPointCut { public void before(){ System.out.println("---------方法执行前--------"); } public void after(){ System.out.println("--------方法执行后--------"); } }
- 去Spring中配制
<!--第二种方式自定义实现--> <!--注册bean--> <bean id="diy" class="demo2.DiyPointCut"/> <!--aop的配置--> <aop:config> <!--使用第二种方式:使用AOP的标签实现--> <aop:aspect ref="diy"> <aop:pointcut id="diyPointCut" expression="execution(* demo1.pojo.UserServiceImpl.*(..))"/> <aop:before method="before" pointcut-ref="diyPointCut"></aop:before> <aop:after method="after" pointcut-ref="diyPointCut"/> </aop:aspect> </aop:config>
- 测试:
public void test2(){ ApplicationContext context = new ClassPathXmlApplicationContext("spring-dao.xml"); UserService userService = context.getBean("userservice",UserService.class); userService.add(); }
- 写我们自己的一个切入类
-
第三种方式,使用注解实现
- 编写一个注解实现的增强类
//使用注解的方法实现增强类 @Aspect public class AnnotationPointCut { @Before("execution(* demo1.pojo.UserServiceImpl.*(..))") public void before(){ System.out.println("--------方法执行前------"); } @After("execution(* demo1.pojo.UserServiceImpl.*(..))") public void after(){ System.out.println("--------方法执行后-------"); } @Around("execution(* demo1.pojo.UserServiceImpl.*(..))") public void around(ProceedingJoinPoint jp) throws Throwable{ System.out.println("环绕前"); System.out.println("签名:"+jp.getSignature()); //执行目标方法proceed Object proceed = jp.proceed(); System.out.println("环绕后:"); System.out.println(proceed); } }
- 在spring配制文件中,注册bean,并增加支持注解的配置
<!--第三种方式:注解实现--> <bean id="userservice" class="demo1.pojo.UserServiceImpl"/> <bean id="annotationPointCut" class="demo3.AnnotationPointCut"/> <aop:aspectj-autoproxy/>
- test
public void test3(){ ApplicationContext context = new ClassPathXmlApplicationContext("spring-dao-3.xml"); UserService userService = context.getBean("userservice",UserService.class); userService.add(); } //结果 环绕前 签名:void demo1.pojo.UserService.add() --------方法执行前------ add 环绕后: null --------方法执行后-------
- 编写一个注解实现的增强类
-
-
整合mybatis
[文档]:https://mybatis.org/spring/zh/-
回忆Mybatis
- 编写pojo的实体类
- 实现mybatis的配置文件,包括连接数据库,别名,mappers
- UserMapper接口编写
- 编写对应的mapper映射文件
- 测试
-
MyBatis-Spring学习
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FSYAMjxv-1598271535944)(image/mybatis_1.jpg)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SnGk24Ea-1598271535945)(image/mybatis_2.jpg)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dVCWWETR-1598271535946)(image/mybatis_3.jpg)]
-
整合实现一:
-
(1)pojo实体类
//建立实体类 @Data public class User { private int id; private String name; private String pwd; }
-
(2) UserMapper.java 接口编写
//建立mapper的接口 public interface UserMapper { public List<User> selectUser(); }
-
(3) UserMapper.xml 映射文件
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="mapper.UserMapper"> <select id="selectUser" resultType="User"> select * from user; </select> </mapper>
-
(4) 引入Spring配置文件spring-dao.xml
<?xml version="1.0" encoding="UTF-8"?> <!--第一步 导入Spring配置文件,包括 beans aop --> <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 ">
-
(5) 配置数据源替换mybatis的数据源 spring-dao.xml
<!--DataSource:使用Spring的数据源替换mybatis的配置 c3p0 dbcp 这里使用 Spring提供的JDBC:org.springframework.jdbc.datasource--> <bean id="datasource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/mybatis?useSSL=true&useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai"/> <property name="username" value="root"/> <property name="password" value="123456"/> </bean>
-
(6)编写mybatis-config.xml
<?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> <typeAliases> <package name="pojo"/> </typeAliases> </configuration>
-
(7) 配置SqlSessionFactory,关联MyBatis spring-dao.xml
<!--配置sqlSessionFactory,关联mybatis--> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="datasource" /> <!--bound mybatis--> <property name="configLocation" value="classpath:mybatis-config.xml"/> <property name="mapperLocations" value="classpath:mapper/*.xml"/> </bean>
-
(8)注册sqlSessionTemplate,关联sqlSessionFactory spring-dao.xml
<!--注册sqlSessionTemplate,关联sqlSessionFactory--> <bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate"> <!--利用构造器注入--> <constructor-arg index="0" ref="sqlSessionFactory"/> </bean>
-
(9) 增加mapper接口的实现类:私有化 sqlSessionTemplate
public class UserMapperImpl implements UserMapper{ private SqlSessionTemplate sqlSessionTemplate; public void setSqlSessionTemplate(SqlSessionTemplate sqlSessionTemplate) { this.sqlSessionTemplate = sqlSessionTemplate; } public List<User> selectUser() { UserMapper mapper = sqlSessionTemplate.getMapper(UserMapper.class); return mapper.selectUser(); } }
- 注意:这里的 mapper.selectUser();对应UserMapper.xml中的id
-
(10) 注册bean实现
<!--注册bean实现--> <bean id="userMapper" class="mapper.UserMapperImpl"> <property name="sqlSessionTemplate" ref="sqlSession"></property> </bean>
- 注意 这里的id=“userMapper”,对应测试类里面的 ”userMapper“
-
(11)测试类
public void test1(){ ApplicationContext context = new ClassPathXmlApplicationContext("spring-dao.xml"); UserMapper userMapper = context.getBean("userMapper", UserMapper.class); for (User user : userMapper.selectUser()) { System.out.println(user); } }
-
-
整合实现2:
-
dao继承Support类,直接利用getSqlSession()获得,然后直接注入S去了S扼杀死哦你Factory,此方法不需要
要管理SqlSessionTemplate -
修改(9)
public class UserMapperImpl2 extends SqlSessionDaoSupport implements UserMapper { public List<User> selectUser() { UserMapper mapper = getSqlSession().getMapper(UserMapper.class); return mapper.selectUser(); } }
-
修改bean的配置,去掉(8),修改(10)
<!--第二种 修改bean Support方式--> <bean id="userMapper" class="mapper.UserMapperImpl2"> <property name="sqlSessionFactory" ref="sqlSessionFactory"></property> </bean>
-
-
-
声明式事物
1.
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dOyxZA7c-1598271535948)(image/affair.jpg)]- 事物的重要性
- 首先 在12的案例中,给UserMapper接口新增两个方法,删除和增加用户 UserMapper.java
public int addUser(User user); public int deleteUser(int id);
- 然后,在UserMapper.xml中,故意把delete写错
<mapper namespace="mapper.UserMapper"> <select id="selectUser" resultType="User"> select * from user; </select> <select id="addUser" parameterType="pojo.User"> insert into user (id,name,pwd) values(#{id},#{name},#{pwd}) </select> <select id="deleteUser" parameterType="int"> deletes from user where id = #{id} </select> </mapper>
-
编写接口的实现类
public class UserMapperImpl2 extends SqlSessionDaoSupport implements UserMapper { public List<User> selectUser() { User user = new User(11,"明明", "123124"); UserMapper mapper = getSqlSession().getMapper(UserMapper.class); mapper.addUser(user); mapper.deleteUser(11); return mapper.selectUser(); } public int addUser(User user) { return getSqlSession().getMapper(UserMapper.class).addUser(user); } public int deleteUser(int id) { return getSqlSession().getMapper(UserMapper.class).deleteUser(id); } }
-
测试
public class UserMapperImpl2 extends SqlSessionDaoSupport implements UserMapper { public List<User> selectUser() { User user = new User(11,"明明", "123124"); UserMapper mapper = getSqlSession().getMapper(UserMapper.class); mapper.addUser(user); mapper.deleteUser(11); return mapper.selectUser(); } public int addUser(User user) { return getSqlSession().getMapper(UserMapper.class).addUser(user); } public int deleteUser(int id) { return getSqlSession().getMapper(UserMapper.class).deleteUser(id); } }
-
结果报异常,但是数据插入进去的
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wFLpNleO-1598271535950)(image/affair_error.png)]
- Spring 声明式事务管理: 将事物管理作为横切关注点,通过aop方法模块化。Spring中通过Spring aop框架支持声明式事务管理
- 加入头文件约束
<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" 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 http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
- JDBC业务
<!--声明式事务--> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <constructor-arg ref="datasource" /> </bean>
- 配置事物的通知
<!--结合aop实现事务置入--> <!--配置事务的类--> <tx:advice id="tx1" transaction-manager="transactionManager"> <!--给哪些方法配置事务--> <!--配置事务的传播特性--> <tx:attributes> <tx:method name="add*" propagation="REQUIRED"/> <tx:method name="delete*" propagation="REQUIRED"/> <tx:method name="update" propagation="REQUIRED"/> <tx:method name="*" propagation="REQUIRED"/> <tx:method name="query" read-only="true"/> </tx:attributes> </tx:advice>
-
事物的传播
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gjlRKWxq-1598271535953)(image/chuanbo.jpg)]
-
- 配置AOP 织入事务
<!--配置事务切入--> <aop:config> <aop:pointcut id="txpointxut" expression="execution(* mapper.*.*(..))"/> <aop:advisor advice-ref="tx1" pointcut-ref="txpointxut"/> </aop:config>
- 整个transacation-spring.xml
<?xml version="1.0" encoding="UTF-8"?> <!--第一步 导入Spring配置文件,包括 beans aop --> <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" 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 http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd"> <!--DataSource:使用Spring的数据源替换mybatis的配置 c3p0 dbcp 这里使用 Spring提供的JDBC:org.springframework.jdbc.datasource--> <bean id="datasource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/mybatis?useSSL=true&useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai"/> <property name="username" value="root"/> <property name="password" value="123456"/> </bean> <!--配置sqlSessionFactory,关联mybatis--> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="datasource" /> <!--bound mybatis--> <property name="configLocation" value="classpath:mybatis-config.xml"/> <property name="mapperLocations" value="classpath:mapper/UserMapper.xml"/> </bean> <!--声明式事务--> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <constructor-arg ref="datasource" /> </bean> <!--结合aop实现事务置入--> <!--配置事务的类--> <tx:advice id="tx1" transaction-manager="transactionManager"> <!--给哪些方法配置事务--> <!--配置事务的传播特性--> <tx:attributes> <tx:method name="add*" propagation="REQUIRED"/> <tx:method name="delete*" propagation="REQUIRED"/> <tx:method name="update" propagation="REQUIRED"/> <tx:method name="*" propagation="REQUIRED"/> <tx:method name="query" read-only="true"/> </tx:attributes> </tx:advice> <!--配置事务切入--> <aop:config> <aop:pointcut id="txpointxut" expression="execution(* mapper.*.*(..))"/> <aop:advisor advice-ref="tx1" pointcut-ref="txpointxut"/> </aop:config> </beans>
- applicationContext.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"> <import resource="transaction-spring.xml"/> <!--第二种 修改bean Support方式--> <bean id="userMapper" class="mapper.UserMapperImpl2"> <property name="sqlSessionFactory" ref="sqlSessionFactory"></property> </bean> </beans>
- test
public void test1(){ ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); UserMapper userMapper = context.getBean("userMapper", UserMapper.class); for (User user : userMapper.selectUser()) { System.out.println(user); } }
- 加入头文件约束
- 事物的重要性