1.Spring
Spring官网:https://spring.io/projects/spring-framework
Spring下载地址:https://repo.spring.io/release/org/springframework/spring/
GitHub:https://github.com/spring-projects/spring-framework
Maven依赖
<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.2.4.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.2.4.RELEASE</version>
</dependency>
优点
- spring是一个开源的免费的框架(容器)
- spring是一个轻量级,非入侵式框架
- 控制反转IOC 、面向切面编程AOP
- 支持事务的处理,对框架整合的支持
总结一句话:
Spring是一个轻量级的控制反转(IOC)和面向切面编程(AOP)的框架
Spring七大模块
2.IOC理论推导
项目:spring_study
模块:spring_01_ioc01
来我们来回顾以下我们以前的程序
UserDao 接口
UserDaoImpl 实现类
UserService 接口
UserServiceImpl 实现类
最后测试
结构如下
上图可以看到 如果一个dao有多个实现类
UserServiceImpl中代码:
public class UserServiceImpl implements UserService{
UserDao userDao = new UserDaoMysql();
public void getUser() {
userDao.getUser();
}
}
如果今天我们用的是UserDaoMysql实现类
明天项目改变,需要用到UserDaoOracle实现类
我们这时候就要回到UserServiceImpl中修改代码
UserDao userDao = new UserDaoOracle();
如果一个程序有十几二十个实现类,每次都要自己来手动改变代码吗?
每一次改动都要在源代码中动手脚,这样的程序不是一个合格的程序
这时候控制反转(IOC)就可以很好的解决此问题
UserServiceImpl代码:
public class UserServiceImpl implements UserService{
private UserDao userDao ;
//动态set注入,控制反转,将主动权给客户端,客户端需要哪个就指定哪个,
// service通过客户端指定的需求去找
public void setUserDao(UserDao userDao){
this.userDao = userDao;
}
public void getUser() {
userDao.getUser();
}
}
测试代码
public class MyTest {
public static void main(String[] args) {
UserServiceImpl userService = new UserServiceImpl();
//客户端指定dao实现类
userService.setUserDao(new UserDaoOracle());
userService.getUser();
}
}
之前,程序是主动创建对象,控制权在程序员手上
使用set注入后,程序不在具有主动性,而是变成了被动的接收对象
3.IOC本质
- IOC: ( Inversion of Control )控制反转
IOC就是控制反转,通俗的说就是我们不用自己创建实例对象,这些都交给Spring的bean工厂帮我们创建管理。这也是Spring的核心思想,通过面向接口编程的方式来是实现对业务组件的动态依赖。这就意味着IOC是Spring针对解决程序耦合而存在的。在实际应用中,Spring通过配置文件(xml或者properties)指定需要实例化的java类(类名的完整字符串),包括这些java类的一组初始化值,通过加载读取配置文件,用Spring提供的方法(getBean())就可以获取到我们想要的根据指定配置进行初始化的实例对象,其实现方式是依赖注入(DI)。
- AOP就是将程序功能中的频繁出现或者与主业务逻辑代码相关度不高的代码抽离出来,通过切面编程的方式在想要调用的时候引入调用的思想。而这种思想并不是只限于Spring和java,AOP(面向切面)和OOP(面向对象)一样都是一种编程思想,这种思想的实现机制在Spring中便是应用了java的动态代理和java的反射。在实际编程中,我们通常会遇到一些交叉业务逻辑(比如:日志,事务,安全等等),这是我们就可以封装一个封面,然后注入到目标对象(具体的业务逻辑)中去。ps:很多方法都会抛出异常信息,这是我们就可以写一个拦截器,在这个类中实现记录错误日志的功能,再在Spring的xml配置文件中配置一个对这些要记录日志的方法的AOP拦截器,在这个方法执行后调用这个拦截器来记录日志。这样就不用每次抛出异常都要手动的去单独处理记录,提高了程序的内聚性。这种在调用某个方法之前/后想要自动执行一系列自定义操作的就是AOP思想。
4.HelloSpring
模块:spring_02_hello
- 用xml的方式创建对象
创建一个hello类
public class Hello {
private String str;
@Override
public String toString() {
return "Hello{" +
"str='" + str + '\'' +
'}';
}
public String getStr() {
return str;
}
//set方法不能少,spring通过set方法进行赋值
public void setStr(String str) {
this.str = str;
}
}
在resources下创建一个xml文件(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">
<!--使用Spring来创建对象,在Spring中这些对象都成为 bean
java: Hello hello = new Hello();
类型 变量名 = new 类型();
spring:
id : 表示变量名
class : 表示 new的对象
property : 表示给对象的属性赋值
name : 对象属性名
value : 要赋的值
-->
<bean id="hello" class="com.it.pojo.Hello">
<property name="str" value="Spring"/>
</bean>
</beans>
测试
import com.it.pojo.Hello;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* @author shkstart
* @create 2020-04-14 11:21
*/
public class MyTest {
public static void main(String[] args) {
//获取Spring上下文对象
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
//getBean(); 获取对象 参数为 xml配置文件中 id的值
Hello hello = (Hello) context.getBean("hello");
//调用hello中的方法
System.out.println(hello.getStr());
}
}
顺势修改模块:spring_01_ioc01中代码
在resources下创建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">
<!--使用Spring来创建对象,在Spring中这些对象都成为 bean
java: Hello hello = new Hello();
类型 变量名 = new 类型();
spring:
id : 表示变量名
class : 表示 new的对象
property : 表示给对象的属性赋值
name : 对象属性名
value : 要赋的值
-->
<bean id="userDaoMysql" class="com.it.dao.UserDaoMysql"/>
<bean id="userDaoOracle" class="com.it.dao.UserDaoOracle"/>
<bean id="userServiceImpl" class="com.it.service.UserServiceImpl">
<!-- ref : 引用spring容器中创建好的对象
value : 具体的值 基本数据类型-->
<property name="userDao" ref="userDaoOracle"/>
</bean>
</beans>
测试
public class MyTest {
public static void main(String[] args) {
//获取ApplicationContext对象
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
//获得容器,需要哪个对象就get哪个
UserServiceImpl userServiceImpl = (UserServiceImpl) context.getBean("userServiceImpl");
//调用方法
userServiceImpl.getUser();
}
}
如果想实现不同操作,去xml中修改配置文件
<property name="userDao" ref="userDaoOracle"/>
到现在我们再也不用去程序中修改代码了,要实现不同的操作,只需要在XML配置文件中进行修改,所谓IOC就一句话:对象由Spring来创建,管理,装配
5. IOC创建对象的方式
模块 spring_03_ioc02
- 默认使用无参构造方法创建对象
<!--无参构造方法创建对象-->
<bean id="user" class="com.it.pojo.User">
</bean>
- 如需使用有参构造方法创建对象
- 1.有参构造方法参数下标
<!--利用有参构造的参数下标来赋值 index 的值为参数的索引--> <bean id="user" class="com.it.pojo.User"> <constructor-arg index="0" value="卡莎-index"/> </bean>
- 2.有参构造方法参数类型(不建议使用)
<!--利用有参构造参数类型赋值
type 的值为参数类型的全类名-->
<bean id="user" class="com.it.pojo.User">
<constructor-arg type="java.lang.String" value="卡莎—type"/>
</bean>
- 3.有参构造方法参数名
<!--利用有参构造参数名赋值-->
<bean id="user" class="com.it.pojo.User">
<constructor-arg name="name" value="卡莎-name"/>
</bean>
总结:在配置文件加载的时候,容器中管理的对象就已经初始化了
6.Spring配置
- 1.alias
<!--别名:给bean取一个别名
name 的值为 bean id值-->
<alias name="user" alias="u"/>
- 2,bean
<!--
id : bean 的唯一标识符,也相当于对象名
class : bean对象对应的全限类名
name : 别名,name别名可以取多个,中间可用逗号\空格\引号...来分割
-->
<bean id="user" class="com.it.pojo.User" name="u1 u2,u3;u4">
</bean>
- 3.import
一般来说一个项目会有很多配置文件 import会将多个配置文件 导入合并为一个总的配置文件使用的时候直接使用总的配置文件即可
<import resource="beans.xml"/>
<import resource="beans2.xml"/>
<import resource="beans3.xml"/>
7.依赖注入(DI)
模块: spring_04_di
依赖:bean对象的创建依赖于容器
注入:bean对象的所有属性,由容器来注入
-
1.构造器方式注入
参考前面5 -
2.set方式注入(重点)
环境搭建
com.it.pojo.Student代码
package com.it.pojo;
import java.util.*;
/**
* @author shkstart
* @create 2020-04-15 9:32
*/
public class Student {
private String name;
private Address address;
private String[] books;
private List<String> hobbys;
private Map<String,String> card;
private Set<String> games;
private String wife;
private Properties info;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
public String[] getBooks() {
return books;
}
public void setBooks(String[] books) {
this.books = books;
}
public List<String> getHobbys() {
return hobbys;
}
public void setHobbys(List<String> hobbys) {
this.hobbys = hobbys;
}
public Map<String, String> getCard() {
return card;
}
public void setCard(Map<String, String> card) {
this.card = card;
}
public Set<String> getGames() {
return games;
}
public void setGames(Set<String> games) {
this.games = games;
}
public String getWife() {
return wife;
}
public void setWife(String wife) {
this.wife = wife;
}
public Properties getInfo() {
return info;
}
public void setInfo(Properties info) {
this.info = info;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", address=" + address +
", books=" + Arrays.toString(books) +
", hobbys=" + hobbys +
", card=" + card +
", games=" + games +
", wife='" + wife + '\'' +
", info=" + info +
'}';
}
}
com.it,pojo.Address代码
package com.it.pojo;
/**
* @author shkstart
* @create 2020-04-15 9:32
*/
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 + '\'' +
'}';
}
}
resources.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
https://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="address" class="com.it.pojo.Address">
<property name="address" value="雄安新区"/>
</bean>
<bean id="student" class="com.it.pojo.Student">
<!--基本数据类型 注入-->
<property name="name" value="卡莎"/>
<!--bean对象 注入 ref引用spring容器的bean-->
<property name="address" ref="address"/>
<!--Array注入-->
<property name="books">
<array>
<value>红楼梦</value>
<value>水浒传</value>
<value>三国演义</value>
<value>西游记</value>
</array>
</property>
<!--List注入-->
<property name="hobbys">
<list>
<value>唱、跳、rap</value>
<value>篮球</value>
</list>
</property>
<!--Map注入-->
<property name="card">
<map>
<entry key="身份证" value="111111111122222222"/>
<entry key="银行卡" value="444444444444444444"/>
</map>
</property>
<!--Set注入-->
<property name="games">
<set>
<value>LOL</value>
<value>CF</value>
</set>
</property>
<!--null值注入-->
<property name="wife">
<null/>
</property>
<!--propertes注入 类似key-value-->
<property name="info">
<props>
<prop key="driver">com.mysql.jdbc.Driver</prop>
<prop key="url">jdbc:msql:localhost:3306/test</prop>
<prop key="username">root</prop>
<prop key="password">xxxxxx</prop>
</props>
</property>
</bean>
</beans>
测试代码
public class MyTest {
public static void main(String[] args) {
//获取spring配置文件上下文对象
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
//利用context.getBean 获取bean
Student student = (Student)context.getBean("student");
//调用bean方法
System.out.println(student);
/*
* 输出结果
* Student{name='卡莎',
* address=Address{address='雄安新区'},
* books=[红楼梦, 水浒传, 三国演义, 西游记],
* hobbys=[唱、跳、rap, 篮球],
* card={身份证=111111111122222222, 银行卡=444444444444444444},
* games=[LOL, CF],
* wife='null',
* info={password=xxxxxx, url=jdbc:msql:localhost:3306/test, driver=com.mysql.jdbc.Driver, username=root}}
* */
}
}
3.扩展注入
新建一个User类
public class User {
private String name;
private int age;
//有参构造必须有,因为要使用c标签注入
public User(String name, int age) {
this.name = name;
this.age = age;
}
public User() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
新建一个userBeans.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"
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">
<!--p 命名空间注入 可以直接注入属性的值 property-->
<bean id="user" class="com.it.pojo.User" p:name="卡莎" p:age="20"/>
<!--c 命名空间注入 通过构造器注入 constructor-args-->
<bean id="user2" class="com.it.pojo.User" c:age="30" c:name="小明"/>
<!--context 可以获取外部配置文件(.properties)-->
<context:property-placeholder location="classpath:db.properties"/>
<bean id="user" class="com.it.pojo.User">
<!--通过通配符 ${key} 获得外部配置文件的值-->
<property name="name" value="${username}"/>
</beans>
测试
@Test
public void test(){
ApplicationContext context = new ClassPathXmlApplicationContext("userBeans.xml");
User user = context.getBean("user", User.class);
User user2 = context.getBean("user2",User.class);
System.out.println(user);
System.out.println(user2);
}
}
注意:如果要使用 p标签注入 \ c标签注入\context标签注入 我们需要导入xml约束
xmlns:p="http://www.springframework.org/schema/p"
http://www.springframework.org/schema/p
https://www.springframework.org/schema/p/spring-p.xsd
xmlns:c="http://www.springframework.org/schema/c"
http://www.springframework.org/schema/c
https://www.springframework.org/schema/c/spring-c.xsd
xmlns:context="http://www.springframework.org/schema/context"
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd
8.Bean作用域
- 单例模式
- Spring默认机制
<!--scope 作用域 spring默认是singleton 单例模式-->
<bean id="user2" class="com.it.pojo.User" c:age="30" c:name="小明" scope="singleton"/>
- 原型模式
- 每次从容器中get 就会new一个新对象
<!--prototype 原型模式 每次get bean 的时候都会创建一个新的对象 -->
<bean id="user2" class="com.it.pojo.User" c:age="30" c:name="小明" scope="prototype"/>
9.Bean的自动装配
- 自动装配是Spring满足bean依赖的一种方式
- Spring会在上下文中自动寻找,并自动给bean装属性
在Spring中有三种装配方式
- 在xml中显式配置
- 在java中显式配置
- 隐式 的自动装配bean【重要】
环境搭建
com.it.pojo.People代码
package com.it.pojo;
/**
* @author shkstart
* @create 2020-04-15 14:10
*/
public class People {
private String name;
private Cat cat;
private Dog dog;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Cat getCat() {
return cat;
}
public void setCat(Cat cat) {
this.cat = cat;
}
public Dog getDog() {
return dog;
}
public void setDog(Dog dog) {
this.dog = dog;
}
@Override
public String toString() {
return "People{" +
"name='" + name + '\'' +
", cat=" + cat +
", dog=" + dog +
'}';
}
}
com.it.pojo.Cat代码
package com.it.pojo;
/**
* @author shkstart
* @create 2020-04-15 14:08
*/
public class Cat {
public void speak(){
System.out.println("The Cat is miao~ miao~ miao~");
}
}
com.it.pojo.Dog代码
package com.it.pojo;
/**
* @author shkstart
* @create 2020-04-15 14:09
*/
public class Dog {
public void speak(){
System.out.println("The Dog is wang~ wang~ wang~");
}
}
applicationContext.xml配置文件
<bean id="cat" class="com.it.pojo.Cat"/>
<bean id="dog" class="com.it.pojo.Dog"/>
正常装配
<bean id="people" class="com.it.pojo.People">
<property name="name" value="人类"/>
<property name="cat" ref="cat"/>
<property name="dog" ref="dog"/>
</bean>
或
<bean id="people" class="com.it.pojo.People"
p:name="人类" p:cat-ref="cat" p:dog-ref="dog"/>
- 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"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="cat" class="com.it.pojo.Cat"/>
<bean id="dog" class="com.it.pojo.Dog"/>
<!--
autowire : 自动装配
byName: 会自动在容器上下文中查找,和自己对象set方法后面的值对应的 bean id
例如 People 中的 setDog(Dog dog) id = dog 对应 setDog 所以自动装配
-->
<bean id="people" class="com.it.pojo.People" autowire="byName">
<property name="name" value="人类"/>
</bean>
</beans>
- byType 自动装配
<?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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="cat" class="com.it.pojo.Cat"/>
<bean id="dog" class="com.it.pojo.Dog"/>
<!--
byType: 会自动在容器上下文中查找,people属性类型的唯一bean
这样一来说明 如果用byType spring上下文中有且只能有一个和
people中属性对应的bean对象,如果有多个则报错
使用ByType 上面的bean 可以不加id
-->
<bean id="people" class="com.it.pojo.People" autowire="byType">
<property name="name" value="人类"/>
</bean>
</beans>
总结:
- byName 的时候,需要保证所有bean的id值唯一,并且这个bean需要和自动注入属性的set方法值一致
- byType 的时候,需要保证所有的bean的class值唯一,并且这个bean需要和自动注入set方法类型一样
使用注解实现自动装配
使用注解实现自动装配需要
导入xml约束
添加 注解支持 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/>
<bean id="cat" class="com.it.pojo.Cat"/>
<bean id="dog" class="com.it.pojo.Dog"/>
<bean id="people" class="com.it.pojo.People"/>
</beans>
@Autowired
给people属性或set方法添加注解@Autowired
package com.it.pojo;
import org.springframework.beans.factory.annotation.Autowired;
/**
* @author shkstart
* @create 2020-04-15 14:10
*/
public class People {
private String name;
@Autowired
private Cat cat;
@Autowired
private Dog dog;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Cat getCat() {
return cat;
}
// @Autowired autowired也可以在set方法中使用 也可以在属性中使用 可以省略set方法
public void setCat(Cat cat) {
this.cat = cat;
}
public Dog getDog() {
return dog;
}
// @Autowired autowired也可以在set方法中使用 也可以在属性中使用 可以省略set方法
public void setDog(Dog dog) {
this.dog = dog;
}
@Override
public String toString() {
return "People{" +
"name='" + name + '\'' +
", cat=" + cat +
", dog=" + dog +
'}';
}
}
@Nullable 和 @Autowired(required = false)的使用
//@Autowired(required = false) 表示该属性可以为null
@Autowired(required = false)
//Nullable 表是该参数可以为null
public People(@Nullable Cat cat ){
this.cat = cat;
}
Autowired 和 Qualifier(value = " xxx") 的组合使用
如果spring容器中存在多个cat bean 但还想要注解自动装配 我们就需要利用Qualifier(value=“xxx”) 来指定一个bean
//required = false 表示该属性可以为null
@Autowired(required = false)
//指定装配的bean为ioc容器中bean id 为 cat11 的bean对象
@Qualifier(value="cat11")
private Cat cat;
@Resource的使用 @Resource(name=“xxx”)
@Resource(name = "cat1")
private Cat cat;
总结:@Resource 和 @Autowired 的区别
- 都是用来总动装配的,都可以放在属性字段上
- @Autowired 是通过byType方式实现的
- @Resource 默认通过byName实现,如果找不到名字,则通过byType
10.使用注解开发
模块:spring_06_annotation
使用注解开发需要确保maven项目下有org.springframework:spring-aop:5.2.4.RELEASE这个包
然后就是导入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:component-scan base-package="com.it"/>
<!--开启注解支持-->
<context:annotation-config/>
</beans>
- 属性的注入
// @Component 等价于 <bean id="user" class="com.it.pojo.User"/>
@Component
public class User {
//@Value 等价于 <property name="name" value="卡莎"/>
@Value("卡莎")
public String name;
-
衍生的注解
-
自动装配注解
上方 9 -
作用域注解
// @Component 等价于 <bean id="user" class="com.it.pojo.User"/>
@Component
@Scope("singleton") // 标注为单例模式,原型模式 @Scope("prototype")
public class User {
- 基本的书写格式
@Component //等价于 <bean id="user" class="com.it.pojo.User"/>
@Scope("singleton") // 标注为单例模式,原型模式 @Scope("prototype")
public class User {
@Value("卡莎")//属性赋值 等价于 <property name="name" value="卡莎"/>
public String name;
@Autowired //自动装配
public Other other;
11.使用Java方式配置Spring
模块:spring_07_appconfig
不需要配置文件,完全用java代码加注解完成spring配置
创建一个配置类 com.it.config.MyConfig
package com.it.config;
import com.it.pojo.User;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
/**
* @author shkstart
* @create 2020-04-16 9:24
*/
@Configuration//这个也会被Spring容器托管,注册到容器中,
//因为它本身就是一个@component
// @Configuration 表示这是一个配置类
//相当于我们之前的applicationContext.xml
@ComponentScan("com.it") //扫描包下的类 该类下的注解可以使用
@Import(MyConfig2.class) //合并其他配置文件
public class MyConfig {
@Bean //@Bean 相当于之前applicationContext.xml中的bean标签
// 方法名 相当于 bean标签的id值
// 返回值类型相当于 bean标签的class
public User getUser(){
return new User(); //返回值就是注入bean中的对象
}
}
User.java代码
package com.it.pojo;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
/**
* @author shkstart
* @create 2020-04-16 9:23
*/
@Component
public class User {
private String name;
public String getName() {
return name;
}
@Value("卡莎")
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
'}';
}
}
我们在编写一个配置类
@Configuration //代表这是一个配置类
public class MyConfig2 {
}
在之前的配置类中我们来选择导入这个配置类
@Configuration
@Import(MyConfig2.class) //导入合并其他配置类,类似于配置文件中的 import 标签
public class MyConfig {}
测试
import com.it.config.MyConfig;
import com.it.pojo.Password;
import com.it.pojo.User;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
/**
* @author shkstart
* @create 2020-04-16 9:31
*/
public class MyTest {
public static void main(String[] args) {
//获取注解信息上下文对象 参数为配置类
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MyConfig.class);
//getBean 参数为 @bean注解下的方法名,返回值类型是@bean注解下方法的返回值类型
User user = (User) context.getBean("getUser");
// Password password = context.getBean("getPassword",Password.class);
System.out.println(user.getName());
// System.out.println(password.getPassword());
}
}
12.静态代理模式
模块:spring_08_proxy
角色分析
- 抽象角色:一般会用接口或抽象类来解决
- 真实角色:被代理的角色
- 代理角色:代理真实角色,并顺带附属一些操作
- 客户:访问代理对象的人
- 抽象角色
package com.it.demo01;
/**
* @author shkstart
* @create 2020-04-16 16:12
*/
//租房
public interface Rent {
void rent();
}
- 真实角色
package com.it.demo01;
/**
* @author shkstart
* @create 2020-04-16 16:11
*/
//房东
public class Host implements Rent{
//房东只出租房子
public void rent(){
System.out.println("房东出租房子");
}
}
- 代理角色
package com.it.demo01;
/**
* @author shkstart
* @create 2020-04-16 16:12
*/
//代理 (中介)
public class Proxy implements Rent{
//组合 获取房东对象
private Host host;
public Proxy() {
}
public Proxy(Host host) {
this.host = host;
}
public void rent(){
showHose();
host.rent();
heTong();
}
public void showHose(){
System.out.println("代理带顾客看房子");
}
public void heTong(){
System.out.println("代理带顾客签合同");
}
}
- 客户 (访问代理)
package com.it.demo01;
/**
* @author shkstart
* @create 2020-04-16 16:11
*/
//顾客
public class Client {
public static void main(String[] args) {
Host host = new Host();
Proxy proxy = new Proxy(host);
proxy.rent();
}
}
代理模式的好处:
- 可以使真实角色的操作更加纯粹,不去关注一些公共业务
- 公共业务交给代理,实现业务分工
- 公共业务发生扩展的时候,方便集中管理
缺点:
- 一个真实角色就会产生一个代理,代码量翻倍
加深理解
demo02包下
13.动态代理
动态代理的角色和静态代理角色一样
动态代理的代理类是自动生成
-
基于接口----- JDK动态代理
-
清楚Proxy 类 和 InvocationHandler接口
- InvocationHandler是由代理实例的调用处理程序实现的接口
- Proxy提供了创建动态代理类和实例的静态方法
demo03
UserService接口 (抽象角色)
package com.it.demo03;
/**
* @author shkstart
* @create 2020-04-16 16:38
*/
//抽象角色
public interface UserService {
void add();
void delete();
void update();
void query();
}
UserServiceImpl (真实角色)
package com.it.demo03;
/**
* @author shkstart
* @create 2020-04-16 16:39
*/
//真实角色
public class UserServiceImpl implements UserService {
public void add() {
System.out.println("添加了一个用户");
}
public void delete() {
System.out.println("删除了一个用户");
}
public void update() {
System.out.println("修改了一个用户");
}
public void query() {
System.out.println("查询了一个用户");
}
}
ProxyInvocationHandler 动态代理类
package com.it.demo03;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* @author shkstart
* @create 2020-04-16 17:27
*/
//用这个类自动生成代理类 需要实现InvocationHandler接口
public class ProxyInvocationHandler implements InvocationHandler {
//被代理的接口
private Object target;
//set方法
public void setTarget(Object target){
this.target = target;
}
//生成得到代理类
public Object getProxy(){
//类Proxy下的newProxyInstance方法
//参数loader - 类加载器来定义代理类
//参数interfaces - 代理类实现的接口列表
//参数h - 调度方法调用的调用处理函数
return Proxy.newProxyInstance(this.getClass().getClassLoader(),
target.getClass().getInterfaces(),this);
}
//处理代理实例并返回结果
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//添加日志功能
log(method.getName());
Object result = method.invoke(target,args);
return result;
}
//添加一个功能 日志功能
public void log(String msg){
System.out.println("执行了" + msg + "方法");
}
}
Client(客户)
package com.it.demo03;
/**
* @author shkstart
* @create 2020-04-16 17:37
*/
public class Client {
public static void main(String[] args) {
//真实角色
UserServiceImpl userService = new UserServiceImpl();
//代理角色 不存在
ProxyInvocationHandler pih = new ProxyInvocationHandler();
//设置需要代理的对象
pih.setTarget(userService);
//动态生成代理类
UserService proxy = (UserService) pih.getProxy();
proxy.add();
}
}
动态代理好处
他具有静态代理的好处
- 一个动态代理代理的是一个接口,一般就是对应一类业务
- 一个动态代理可以代理多个类,只要实现了同一个接口即可
14.Spring实现AOP
模块: spring_09_aop
使用AOP织入,需要导入依赖
<!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.5</version>
</dependency>
方式一:使用spring的API接口【Spring API 接口实现】
afterLog.java代码
package com.it.log;
import org.springframework.aop.AfterReturningAdvice;
import java.lang.reflect.Method;
/**
* @author shkstart
* @create 2020-04-17 17:06
*/
//实现 AfterReturningAdvice
public class AfterLog implements AfterReturningAdvice {
//afterReturning方法 意味着 UserServiceImpl方法执行完执行
//参数:
//returnValue : 返回值类型
//method : 要执行目标对象方法
//args : 参数值
//target : 目标对象
public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
System.out.println("执行了" + method.getName() + "方法,返回了"+returnValue);
}
}
beforeLog.java代码
package com.it.log;
import org.springframework.aop.MethodBeforeAdvice;
import java.lang.reflect.Method;
/**
* @author shkstart
* @create 2020-04-17 17:00
*/
//实现 MethodBeforeAdvice
public class BeforeLog implements MethodBeforeAdvice {
//before方法 意味在UserServiceImpl(真实角色)下方法执行之前执行
//参数:
//method : 要执行的目标对象方法
//args : 参数
//target : 目标对象
public void before(Method method, Object[] args, Object target) throws Throwable {
System.out.println(this.getClass().getName() + "的" + method.getName() + "方法被执行了");
}
}
接口UserService
package com.it.service;
/**
* @author shkstart
* @create 2020-04-17 16:59
*/
//抽象角色
public interface UserService {
void add();
void delete();
void update();
void select();
}
接口实现类UserServiceImpl
package com.it.service;
/**
* @author shkstart
* @create 2020-04-17 16:59
*/
//真实角色
public class UserServiceImpl implements UserService {
public void add() {
System.out.println("添加了一个用户");
}
public void delete() {
System.out.println("删除了一个用户");
}
public void update() {
System.out.println("更新了一个用户");
}
public void select() {
System.out.println("查询了一个用户");
}
}
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"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
https://www.springframework.org/schema/aop/spring-aop.xsd">
<!--注册bean到Spring-->
<bean id="userService" class="com.it.service.UserServiceImpl"/>
<bean id="afterLog" class="com.it.log.AfterLog"/>
<bean id="beforeLog" class="com.it.log.BeforeLog"/>
<!--方式一:使用原生的Spring API接口-->
<!--配置AOP 导入AOP约束-->
<aop:config>
<!--切入点
id:切入点名
expression: 要切入到哪个类中的哪个方法
execution(修饰符 返回值 包名.类名/接口名.方法名(参数列表))
execution(* com.it.service.UserServiceImpl.*(..) )
↑ * : 表示 返回的所有类型
com.it.service.UserServiceImpl : 表示要执行方法的类的全类名
.* : 表示此类下的所有方法
(..) : 表示方法中的参数
-->
<aop:pointcut id="pointcut" expression="execution(* com.it.service.UserServiceImpl.*(..) )"/>
<!--执行环绕增加
将beforeLog类对象和afterLog类对象 切入到 pointcut这个切入点中
也就是插入到UserServiceImpl类方法中
advice-ref = 要插入类的bean id
pointcut-ref= 切入的点 id
-->
<aop:advisor advice-ref="beforeLog" pointcut-ref="pointcut"/>
<aop:advisor advice-ref="afterLog" pointcut-ref="pointcut"/>
</aop:config>
</beans>
测试
import com.it.service.UserService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* @author shkstart
* @create 2020-04-17 17:29
*/
public class MyTest {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
//动态代理的是接口 而不是实现类
UserService userService = (UserService) context.getBean("userService");
userService.add();
}
}
方式二:自定义类 不实现接口(切面)【切面自定义】
新建一个diy包
DiyPointCut.java
package com.it.diy;
/**
* @author shkstart
* @create 2020-04-17 18:21
*/
public class DiyPointCut {
public void before(){
System.out.println("方法执行之前执行");
}
public void after(){
System.out.println("方法执行之后执行");
}
}
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"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
https://www.springframework.org/schema/aop/spring-aop.xsd">
<!--注册bean到Spring-->
<bean id="userService" class="com.it.service.UserServiceImpl"/>
<bean id="afterLog" class="com.it.log.AfterLog"/>
<bean id="beforeLog" class="com.it.log.BeforeLog"/>
<!--方式二:自定义类 切面
自定义类 将此类作为切面通过切入点切入到类中
自定义的类 ==> 切面aop:aspect ==> 切入点 aop:pointcut ==> 通知(类似环绕增加)-->
<!--将自定的类注册到Spring中-->
<bean id="diy" class="com.it.diy.DiyPointCut"/>
<!--配置AOP 添加约束-->
<aop:config>
<!--切面 ref 自定义的类-->
<aop:aspect ref="diy">
<!--切入点-->
<aop:pointcut id="pointcut" expression="execution(* com.it.service.UserServiceImpl.*(..))"/>
<!--通知 method:要加入的方法名 pointcut-ref 要加入的切入点id-->
<aop:after method="after" pointcut-ref="pointcut"/>
<aop:before method="before" pointcut-ref="pointcut"/>
</aop:aspect>
</aop:config>
</beans>
方式三:使用注解实现AOP
创建一个类 AnnotationPointCut
AnnotationPointCut代码
package com.it.diy;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
/**
* @author shkstart
* @create 2020-04-18 9:08
*/
@Aspect //使用注解标记这是一个切面
public class AnnotationPointCut {
//execution 切入点,将方法切入到那个类的哪个方法中
@Before("execution(* com.it.service.UserServiceImpl.*(..))")
public void before(){
System.out.println("方法执行前------");
}
@After("execution(* com.it.service.UserServiceImpl.*(..))")
public void after(){
System.out.println("方法执行后----------");
}
@Around("execution(* com.it.service.UserServiceImpl.*(..))")
public void around(ProceedingJoinPoint pj) throws Throwable {
System.out.println("环绕增强执行前");
pj.proceed();
System.out.println("环绕增强执行后");
}
}
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"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
https://www.springframework.org/schema/aop/spring-aop.xsd">
<!--注册bean到Spring-->
<bean id="userService" class="com.it.service.UserServiceImpl"/>
<bean id="afterLog" class="com.it.log.AfterLog"/>
<bean id="beforeLog" class="com.it.log.BeforeLog"/>
<!--方式三:利用注解实现AOP-->
<!--注册类到spring-->
<bean id="annotationPointCut" class="com.it.diy.AnnotationPointCut"/>
<!--开启注解支持-->
<aop:aspectj-autoproxy/>
</beans>
测试
import com.it.service.UserService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* @author shkstart
* @create 2020-04-17 17:29
*/
public class MyTest {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
//动态代理的是接口 而不是实现类
UserService userService = (UserService) context.getBean("userService");
userService.add();
}
}
自我总结:我认为的AOP就是在一个已经封装好的类中,再加入一些功能型方法,在不改变源代码、不破坏原来代码结构的前题下,我们需要一个切面和切入点将要增加的代码横向插入到原来的类中
15.Spring整合Mybatis
模块:spring_10_mybatis
mybatis-spring文档:http://mybatis.org/spring/zh/sqlsession.html
导入依赖包
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>spring_study</artifactId>
<groupId>org.example</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>spring_10_mybatis</artifactId>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.2</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.6</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.2.4.RELEASE</version>
</dependency>
<!--Spring操作数据库还需要spring-jdbc -->
<!-- https://mvnrepository.com/artifact/org.springframework/spring-jdbc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.2.4.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.5</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis-spring -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>2.0.4</version>
</dependency>
</dependencies>
<!--在build中配置resources,防止资源导出失败-->
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>true</filtering>
</resource>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>true</filtering>
</resource>
</resources>
</build>
</project>
结构
编写mybatis模板,参考mybatis学习笔记
https://blog.csdn.net/weixin_44900198/article/details/105385963
创建spring-dao.xml配置文件
<?xml version="1.0" encoding="utf8"?>
<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
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
https://www.springframework.org/schema/aop/spring-aop.xsd">
<!--DataSource:使用spring配置替换mybatis中的DataSource配置
我们这里使用spring提供的jdbc
org.springframework.jdbc.datasource.DriverManagerDataSource
-->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mybatis?useUnicode=true&characterEncoding=UTF-8"/>
<property name="username" value="root"/>
<property name="password" value="001129"/>
</bean>
<!--SqlSessionFactory : 使用spring提供的SqlSessionFactroyBean
用来创建 SqlSessionTemplate
-->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!--绑定DataResource 相当于mybatis的DataResource标签-->
<property name="dataSource" ref="dataSource"/>
<!--绑定mybatis配置文件 mybatis-config.xml 能做的事 Spring都可以做-->
<property name="configLocation" value="classpath:mybatis-config.xml"/>
<!--绑定Mapper映射 相当于mybatis下的 mapper标签-->
<property name="mapperLocations" value="classpath:com/it/dao/*.xml"/>
</bean>
<!--SqlSessionTemplate 相当于 SqlSession-->
<bean id="sqlSessionTemplate" class="org.mybatis.spring.SqlSessionTemplate">
<!--通过构造器方式传入 SqlSessionFactory 因为没有set方法-->
<constructor-arg name="sqlSessionFactory" ref="sqlSessionFactory"/>
</bean>
</beans>
mybatis-config.xml配置文件
<?xml version="1.0" encoding="utf8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<!--至此 我们的mybatis配置文件中大部分配置
都已经在spring配置文件中配置完成
mybatis配置文件只需要留一些 其他配置
例如 别名typeAliases
设置 setting 等等-->
<!--configuration 核心配置文件-->
<configuration>
<settings>
<setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>
<typeAliases>
<package name="com.it.pojo"/>
</typeAliases>
</configuration>
applicationContext.xml配置文件
<?xml version="1.0" encoding="utf8"?>
<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
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
https://www.springframework.org/schema/aop/spring-aop.xsd">
<!--总的项目配置文件只负责注册bean
其余的操作 比如操作数据库 交给其他的配置文件
我们最后只需要合并即可
-->
<!--导入 spring-dao.xml 配置文件-->
<import resource="spring-dao.xml"/>
<!--将实现类注册到Spring中
我们只需要调用这个类下的方法就可以实现操作
-->
<bean id="userServiceImpl" class="com.it.dao.UserMapperImpl">
<property name="sqlSessionTemplate" ref="sqlSessionTemplate"/>
</bean>
</beans>
com.it.pojo.User.java
package com.it.pojo;
/**
* @author shkstart
* @create 2020-04-18 10:03
*/
public class User {
private int id;
private String name;
private String password;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", name='" + name + '\'' +
", password='" + password + '\'' +
'}';
}
}
com.it.dao.UserMapper接口
package com.it.dao;
import com.it.pojo.User;
import java.util.List;
/**
* @author shkstart
* @create 2020-04-18 10:05
*/
public interface UserMapper {
List<User> selectUser();
}
com.it.dao.userMapper.xml 接口实现配置文件
<?xml version="1.0" encoding="utf8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.it.dao.UserMapper">
<select id="selectUser" resultType="user">
select * from user ;
</select>
</mapper>
com.it.dao.userMapperImpl实现类
import java.util.List;
/**
* @author shkstart
* @create 2020-04-18 10:54
*/
//创建实现类
public class UserMapperImpl implements UserMapper {
//获取SqlSessionTemplate 就相当于SqlSession都是增删改查操作
private SqlSessionTemplate sqlSessionTemplate;
//set注入方法
public void setSqlSessionTemplate(SqlSessionTemplate sqlSessionTemplate){
this.sqlSessionTemplate = sqlSessionTemplate;
}
public List<User> selectUser() {
//通过SqlSessionTemplate.getMapper 方法获取UserMapper
UserMapper userMapper = sqlSessionTemplate.getMapper(UserMapper.class);
//执行selectUser方法
return userMapper.selectUser();
}
}
测试
import com.it.dao.UserMapper;
import com.it.dao.UserMapperImpl;
import com.it.pojo.User;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
/**
* @author shkstart
* @create 2020-04-18 10:08
*/
public class MyTest {
@Test
public void selectUser() throws IOException {
/* String resources = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resources);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
UserMapper usermapper = sqlSession.getMapper(UserMapper.class);
List<User> list = usermapper.selectUser();
for (User user : list) {
System.out.println(user);
}*/
//上面利用mybatis的繁琐操作可以省略了
//获取Spring配置文件上下文对象
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
//通过getBean 创建并获取对象
UserMapperImpl userServiceImpl = context.getBean("userServiceImpl", UserMapperImpl.class);
//掉用对象的方法
List<User> list = userServiceImpl.selectUser();
for (User user : list) {
System.out.println(user);
}
}
}
总结方式一:整合Mybatis Spring
基本步骤
- 创建操作数据库的配置文件 也就是替换mybatis-config.xml 里内容的配置文件
- 在此配置文件中配置 数据源DataSource 和 SqlSessionFactory 和 SqlSessionTemplate
- 编写一个Mapper实现类 操作方法在此类中
- 将此类注册到spring
- 测试
16.声明式事务
spring-dao.xml
<!--配置声明事务-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<!--结合AOP实现事务织入-->
<!--配置事务通知-->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<!--给那些方法配置事务-->
<!--配置事务的传播特性 propagation-->
<tx:attributes>
<!--propagation="required" 表示 支持当前事务,如果没有事务创建一个事务-->
<tx:method name="add" propagation="REQUIRED"/>
<tx:method name="delete" propagation="REQUIRED"/>
<tx:method name="update" propagation="REQUIRED"/>
<tx:method name="query" read-only="true"/>
<tx:method name="*" propagation="REQUIRED"/>
</tx:attributes>
</tx:advice>
<!--配置事务切入-->
<aop:config>
<!--配置切入点-->
<aop:pointcut id="txPointCut" expression="execution(* com.it.dao.*.*(..))"/>
<!--将通知切入到切入点中-->
<aop:advisor advice-ref="txAdvice" pointcut-ref="txPointCut"/>
</aop:config>