2021-6-23-------------01-1spring----IOC

01-1spring---IOC

  • 1、简介
    • 1.2、优点
    • 1.3、组成
    • 1.4、拓展
  • 2、IOC理论推导
  • 3.IOC获取对象的方式
  • 4、IOC创建对象的方式
    • (1)通过类的无参构造方法来创建对象
    • (2)通过指定的构造器来创建对象
    • (3)通过工厂创建对象
      • i.通过静态工厂创建对象
      • ii通过实例工厂创建对象
      • iii.spring工厂创建对象
  • 4、spring配置
    • 4.1、别名
    • 4.2、Bean配置
      • a单例和多例
        • 单例模式的生命周期:
        • 多例模式生命周期
      • b.懒加载机制
      • d. 方法的创建和销毁
      • c.别名
    • 4.3、import
  • 5、DI依赖注入
    • 5.0三个概念
      • 元数据的作用
      • 配置元数据的方式:
    • 5-0、两类容器
      • 第一种:BeanFactory接口的XmlBeanFactory实现类//过时
      • 第二种:ApplicationContext实现类
    • 5.1构造器注入
    • 5.2、通过set方式注入(普通属性的注入)
    • 5.3、集合的注入方式注入
    • 5.4自动装配的注入
    • 5.5、注解方式
    • 注解属性值
    • 配置实例工厂
    • Autowired和Qualifer
      • 其他注解
    • 5.6、扩展方式
  • 6、Bean作用域
    • 6.1、bean定义
    • 6.2、bean的作用域
      • 1.单例模式
      • 2、原型模式
      • 3、其余的只能在web开发中使用
    • 6.3、Bean的生命周期配置
      • 各个状态机
      • 后置处理器的重写
  • 7、bean的自动装配
    • 1、在xml中显示装配
      • 1.1byName自动装配
      • 1.2byType自动装配
    • 2、使用注解自动装配
    • 3、隐式自动装配【重要】
  • 8、使用注解开发
    • 1、bean
    • 2、属性注解
    • 3、衍生注解
    • 4、自动配置注解
    • 5、作用域
    • 6、小结
  • 9、完全使用java的配置spring
  • 10、代理模式
    • 10.1、静态代理
    • 10.2、加深理解
    • 10.3、动态代理
  • 12、整合Mybatis
    • 1、导入相关jar包
    • 编写一个实体类
    • 编写接口UserMapper
    • 编写配置映射文件UserMapper.xml
    • 编写mybatis-config.xml
    • 编写spring-dao.xml连接数据源
    • 编写UserMapperImpl实现类
    • 编写application.xml
    • 编写测试类
  • 13、声明式事务
    • 实体类
    • 接口
    • UserMapper.xml
    • UserMapperImpl2.java
    • mybatis-config.xml
    • spring-dao.xml
    • application.xml
    • 测试:
  • pom.xml依赖配置

1、简介

2002年,首次推出了spring框架的的雏形,interface21框架

2004年,以interface21为基础,经过重新设计,并且不断丰富其内涵,于2004年发布了1.0版本

spring理念:使现有的技术更加容易使用,整合了现有的技术

SSH:struts2+spring+Hibernate

SSM:SpringMVC+Spring+Mybatis

中文文档:.1.3.RELEASE/reference.

// A code block
<!-- .springframework/spring-webmvc -->
<dependency><groupId>org.springframework</groupId><artifactId>spring-webmvc</artifactId><version>5.3.3</version>
</dependency>
<!-- .springframework/spring-jdbc -->
<dependency><groupId>org.springframework</groupId><artifactId>spring-jdbc</artifactId><version>5.3.3</version>
</dependency>

1.2、优点

  • spring是一个免费的开源框架
  • spring是一个轻量级的、非入侵式的框架
  • 控制反转(IOC),面向切面编程(AOP)
  • 支持事务的处理对框架整合的支持

总结:spring是一个轻量级的控制反转和面向切面编程的框架

1.3、组成

1.4、拓展

现代化开发:基于spring开发

springboot

  • 一个快速开发的脚手架
  • 基于springboot可以快速开发单个微服务

Spring Cloud

  • 基于springBoot实现的

大多数公司都使用springboot进行快速开发,学习springboot前提,需要完全掌握spring和springmvc

spring的弊端:

发展了太久,违背了原来的理念,配置十分繁琐,配置地狱

2、IOC理论推导

Ioc概念:控制反转,Inversion of Control

控制:对象控制——-spring控制

反转:spring设置对象、其他资源


在初始化一个spring容器时,spring会解析指定的xml文件,当解析到其中的bean标签时,会根据该标签中class属性指定的类的全路径名,通过反射来创建该类的对象,并将对象存入内置的map中管理,其中键就是该标签的id,值就是对象。
之后,当通过getbean方法来从容器中获取对象时其实就是根据传入的条件在内置的map中寻找是否有匹配的兼职,如果有则将键值对中保存的对象返回,如果没有就抛出异常。


对象由spring创建和管理

1、UserDao

// A code block
public interface UserDao {void getUser();
}

2、UserDaoImpl

public class UserDaoImpl implements UserDao{@Overridepublic void getUser() {System.out.println("实现了接口");}
}
public class UserDaoMysqlImpl implements UserDao{@Overridepublic void getUser() {System.out.println("实现了mysql");}
}

3、UserService业务接口

public interface UserService {void getUser();
}

4、UserServiceImpl业务实现类

​ //利用set方法实现了动态注入

public class UserServiceImpl implements UserService{UserDao userDao;//利用set方法实现了动态注入public void setUserDao(UserDao userDao) {this.userDao = userDao;}@Overridepublic void getUser() {userDao.getUser();}
}
public class Test {public static void main(String[] args) {UserService userService=new UserServiceImpl();((UserServiceImpl) userService).setUserDao(new UserDaoMysqlImpl());userService.getUser();}
}

之前,程序是主动创建对象,控制权在程序员手上

使用了set注入后程序员不再有主动性,而是变成了被动接受对象!

这种思想从本质上解决了问题,我们程序员不用再管理对象的创建了。系统的耦合性大大降低,可以更加专注在业务的实现上,这是IOC的核心原理
xml


<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns=""xmlns:xsi=""xsi:schemaLocation="://www.springframework.org/schema/beans/spring-beans.xsd"><!--使用spring创建对象,在spring中这些都称为Bean--><bean id="UserDaoImpl" class="com.kuangshen.dao.UserDaoImpl"/><bean id="UserDaoMysqlImpl" class="com.kuangshen.dao.UserDaoMysqlImpl"/><bean id="UserServiceImpl" class="com.kuangshen.service.UserServiceImpl"><!--ref :引用Spring容器中创建好的对象--><property name="userDao" ref="UserDaoImpl"/></bean></beans>

控制反转

概念:
控制反转就是将对象的创建和生命周期的管理过程交给spring去处理,从此开发中不需要关注对象的创建和生命周期的管理,而是在需要时由spring来提供。

DI:在创建对象的过程中spring可以依据配置对对象的属性进行设置

  • 是一种思想,DI(依赖注入)实现IOC的一种方法,没有IOC的程序中我们使用面向对象编程
  • 获得依赖对象的方式反转了。

采用XML的配置Bean的时候,Bean的定义信息是和实现是分离的。而采用注解的方式可以把两者合为一体,Bean的信息直接以注解的形式定义在实现类里面,从而达到零配置的目的。

package com.kuangshen.pojo;/*** @author pcy* @date 2021/2/14 - 15:29*/
public class Hello {private String str;public String getStr() {return str;}//必须有set方法public void setStr(String str) {this.str = str;}@Overridepublic String toString() {return "Hello{" +"str='" + str + '\'' +'}';}
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns=""xmlns:xsi=""xsi:schemaLocation="://www.springframework.org/schema/beans/spring-beans.xsd"><!--使用spring创建对象,在spring中这些都称为Bean--><bean id="hello" class="com.kuangshen.pojo.Hello"><property name="str" value="Spring"/></bean></beans>
import com.kuangshen.pojo.Hello;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;/*** @author pcy* @date 2021/2/14 - 15:38*/
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());}
}

3.IOC获取对象的方式

1).通过id获取bean
2).通过class来获取bean

@Testpublic void eatTest(){//初始化容器ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");/*** 通过id获取bean*/
//        Person person = (Person) context.getBean("Person");
/*** 通过class来获取bean*/Person per = context.getBean(Person.class);ClassPathXmlApplicationContext context1 = (ClassPathXmlApplicationContext) context;context1.close();}

4、IOC创建对象的方式

(1)通过类的无参构造方法来创建对象

Person.java

public class Person {public void eat(){System.out.println("人们在吃饭");}
}

applicationContext.xml

<!--推论1:不能配置多个id相同的bean推论2:可以配置多个类相同,但是id不同的bean推论3:不能配置多个id相同的bean--><bean id="com.pcy.Person" class="com.pcy.Person"></bean>

(2)通过指定的构造器来创建对象

public Person(String name,int age) {System.out.println("name:"+name+",age:"+age);}

applicationContext.xml

<bean id="person" class="com.pcy.Person" scope="singleton" lazy-init="true">
<!--
index:代表第几个参数
name:什么名字的参数
type:参数类型
value和ref:
value:引用类型或者是String类型
ref:赋予值(引用数据类型)
index、name、type不需要都设置,只要没有歧义就可以了
--><constructor-arg index="0" value="lili"/><constructor-arg index="1" value="10"/></bean>

(3)通过工厂创建对象

如果创建对象需要若干设置后才能使用,spring就可以通过工厂类将创建对象的细节封装

i.通过静态工厂创建对象

NetConn.java

public class NetConn {public void _login(){System.out.println("正在登陆");}public void _index(){System.out.println("验证密码");}public void _sendData(){System.out.println("发送数据");}
}

NetConnFactory .java

public class NetConnFactory {private NetConnFactory(){}public static NetConn getNc(){NetConn conn=new NetConn();conn._index();conn._login();return conn;}}
<bean id="netConnFactory" class="com.pcy.NetConnFactory" factory-method="getNc">

原理图

ii通过实例工厂创建对象

NetConnInstanceFactory.java

public class NetConnInstanceFactory {public NetConn getNc(){NetConn conn=new NetConn();conn._index();conn._login();return conn;}
}
  <bean id="netConnInstanceFactory" class="com.pcy.NetConnInstanceFactory"></bean><bean id="net" factory-bean="netConnInstanceFactory" factory-method="getNc"></bean>

iii.spring工厂创建对象

spring内置接口FactoryBean,也可以实现这个接口来开发spring工厂目标类
NetConnSpringFactory .java

public class NetConnSpringFactory implements FactoryBean<NetConn>{@Overridepublic NetConn getObject() throws Exception {NetConn netConn=new NetConn();netConn._login();netConn._index();return netConn;}/*** 获取目标对象类型的方法* @return*/@Overridepublic Class<?> getObjectType() {return NetConn.class;}//控制对象是否是单例@Overridepublic boolean isSingleton() {return false;}
}

applicationContext.xml

        <bean id="netSpringFactory" class="com.pcy.NetConnSpringFactory"></bean>

总结:在配置文件加载的时候,容器中管理的对象就已经初始化了。

4、spring配置

4.1、别名

<!--别名:如果添加了别名也可以通过别名来获取对象-->
<alias name="user" alias="user2"/>

4.2、Bean配置

a单例和多例

spring在默认情况下是单例的,一个bean只会创建一个对象,无论创建多少个对象都返回的是一个对象
优点:减少了对象的创建,从而减少内存的消耗

<bean id="person" class="com.pcy.Person" scope="singleton"></bean>

在实际开发中是存在多例的需求的,所以bean有多例模式

<bean id="person" class="com.pcy.Person" scope="prototype"></bean>

单例模式的生命周期:

spring在启动时,解析xml发现bean标签后,直接创建该bean对象存入map的内部,无论调用多少次getBean都是该bean从map中获取对象返回,一直是一个对象,一直被spring容器持有,直到容器退出

多例模式生命周期

spring容器启动时,发现该bean进行管理,并不会创建对象,此后每次使用geBean都是重新创建该对象返回,每次都是一个新的对象,这个对象spring容器并不会被spring容器持有,什么时候销毁取决于用户。

b.懒加载机制

spring容器初始化的过程中,解析xml,并将单例的bean创建并保存到map中,这样的机制在bean比较少时问题不大,一旦bean非常多时,spring会花费大量的时间创建bean,大量的空间存储bean,所以spring提供了懒加载机制。
懒加载机制:
可以规定bean在spring启动时不立即创建,而是在后续使用的时候才创建

注意
只对单例bean标签使用,因为多例本身是懒加载
单例bean标签使用懒加载之后还是单例

        <bean id="person" class="com.pcy.Person" scope="prototype" lazy-init="true">

全局懒加载

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns=""xmlns:xsi=""xsi:schemaLocation=" .xsd"default-lazy-init="true">
</beans>

如果同时设定全局和指定bean懒加载机制,且配置不相同,则对于该bean局部配置覆盖全局配置

d. 方法的创建和销毁

ProDao.java

public class ProDao {public ProDao() {System.out.println("ProdDao 被创建。。。");}public void init(){System.out.println("init。。连接数据库。。。。。");}public void destory(){System.out.println("destory。。断开数据库。。。。。");}public void  addProd(){System.out.println("增加商品。。");}public void  updateProd(){System.out.println("修改商品。。");}public void  delProd(){System.out.println("删除商品。。");}public void  queryProd(){System.out.println("查询商品。。");}}
<bean id="prodao" class="com.pcy.ProDao" init-method="init" destroy-method="destory"></bean>

c.别名

<!--id:bean的唯一标识符,也就是相当于我们学过的对象名class:bean对象所对应的全限定名name:也是别名,而且Name更加高级,可以同时多个别名,或者用空格分隔,或者用逗号分隔--><bean id="user" class="com.kuangshen.pojo.User" name="user3 u2" scope="prototype"><constructor-arg name="name" value="wang"/></bean>

4.3、import

一般用于团队开发使用,他可以将多个配置文件导入合并为一个

<import resource="applicationContext.xml"/>

使用的时候直接使用一个总的就可以了

5、DI依赖注入

在对象创建时操作其属性

5.0三个概念

依赖:组件之间的关系依赖

注入:注入某个类所依赖的组件,告诉spring如何创建管理对象

元数据:媒体数据,中间数据,就是告诉spring如何创建管理时所说的话

元数据的作用

spring通过元数据提供的指令(配置),容器知道对那些对象进行实例化,配置和组装。

配置元数据的方式:

xml,注解,代码

5-0、两类容器

第一种:BeanFactory接口的XmlBeanFactory实现类//过时

XmlBeanFactory factory = new XmlBeanFactory(new ClassPathResource("bean.xml"));

第二种:ApplicationContext实现类

//第一种实现类
//绝对路径	
//该容器从 XML 文件中加载已被定义的 Bean,需 要给构造器提供完整的路径
ApplicationContext context = new FileSystemXmlApplicationContext("");
//从 classpath 中搜索 bean 配置文件
//该容器从 XML 文件中加载已被定义的 Bean,不
需要提供完整路径,只需正确配置 classpath 下的文件名称即可,因为容器会从
classpath 中搜索 bean 配置文件,classpath 是编译后的 class 文件所在路径ApplicationContext context =new 
ClassPathXmlApplicationContext("SpringBeans.xml");

5.1构造器注入

5.2、通过set方式注入(普通属性的注入)

依赖注入:set注入

依赖:bean对象的创建依赖于容器

注入:bean对象中的所有属性,由容器来注入

package com.kuangshen.pojo;import java.util.*;/*** @author pcy* @date 2021/2/14 - 17:19*/
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;@Overridepublic String toString() {return "Student{" +"name='" + name + '\'' +", address=" + address +", books=" + Arrays.toString(books) +", hobbys=" + hobbys +", card=" + card +", games=" + games +", wife='" + wife + '\'' +", info=" + 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;}
}
package com.kuangshen.pojo;/*** @author pcy* @date 2021/2/14 - 17:20*/
public class Address {private String address;public String getAddress() {return address;}public void setAddress(String address) {this.address = address;}public Address(String address) {this.address = address;}
}
<bean id="student" class="com.kuangshen.pojo.Student"><!--第一种--><property name="name" value="pcy"/></bean>

5.3、集合的注入方式注入

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns=""xmlns:xsi=""xsi:schemaLocation="://www.springframework.org/schema/beans/spring-beans.xsd"><bean id="student" class="com.kuangshen.pojo.Student"><!--第一种--><property name="name" value="pcy"/><!--第二种:bean注入 ref注入--><property name="address" ref="address"/><!--数组的注入--><property name="books"><array><value>d</value><value>y</value><value>s</value></array></property><!--list注入--><property name="hobbys"><list><value>d</value><value>y</value><value>s</value></list></property><!--map--><property name="card"><map><entry key="身份证" value="wsssds"/><entry key="银行卡" value="2343"/></map></property><!--set--><property name="games"><set><value>s</value><value>d</value></set></property><!--prop注入--><property name="info"><props><prop key="12">xin</prop><prop key="13">lihai</prop></props></property><!--null值--><property name="wife"><null/></property></bean><bean id="address" class="com.kuangshen.pojo.Address"><property name="address" value="西安"/></bean>
</beans>

5.4自动装配的注入

全局装配和局部装配

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns=""xmlns:xsi=""xsi:schemaLocation=" .xsd"default-lazy-init="true"default-autowire="byName">
<!--    全局装配-->
<!--    自动装配
byName:遇到要注入的自定义bean类型数据时,按照bean的属性名来同名的id的bean来进行注入
如果找不到就不会注入,返回的值是null
byType:按照bean的类型来找同类型的bean来进行注入
--><bean id="person" class="com.pcy.Person" autowire="byName"></bean><bean id="dog" class="com.pcy.Dog"><property name="name" value="丽丽"></property><property name="age" value="10"></property></bean>
</beans>

5.5、注解方式

  • 加入spring-aop的jar包
  • 并且加入消息头使得注解生效
    applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns=""xmlns:context=""xmlns:xsi=""xsi:schemaLocation="://www.springframework.org/schema/beans/spring-beans-3.2.xsd://www.springframework.org/schema/context/spring-context-3.2.xsd">
<!--    配置包扫描-->
<!--    注解方式实现IOC,
id:推断准则,如果明确指定id,则采用指定的id
如果没有指定的id,则自动推断id
自动推断id的规则
看类名第二个字母,如果第二个字母是小写,则首字母也小写为id
--><context:component-scan base-package="com.pcy.domain"/>

Person.java

@Component("person")//<bean id="person">
public class Person {
}

注解属性值

@Component("person")//<bean id="person">
public class Person {@Autowiredprivate Dog dog;//@Value("丽丽")//加载配置文件的读取方式@Value("${name}")private String name;@Value("${age}")private int age;//读取集合,map,properties等@Value("#{@list}")private List<String> list;@Value("#{@set}")private Set<String> set;@Value("#{@map}")private Map<String,String> map;@Value("#{@properties}")private Properties properties;@Overridepublic String toString() {return "Person1{" +"name='" + name + '\'' +", age=" + age +", list=" + list +", set=" + set +", map=" + map +", properties=" + properties +'}';}
}

applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns=""xmlns:context=""xmlns:xsi="" xmlns:util=""xsi:schemaLocation="://www.springframework.org/schema/beans/spring-beans-3.2.xsd://www.springframework.org/schema/context/spring-context-3.2.xsd  .xsd"><!--    配置包扫描-->
<!--    注解方式实现IOC,
id:推断准则,如果明确指定id,则采用指定的id
如果没有指定的id,则自动推断id
自动推断id的规则
看类名第二个字母,如果第二个字母是小写,则首字母也小写为id
--><context:component-scan base-package="com.pcy.domain"/><!--    开启注解方式的DI,支持DI以注解方式来注入数据--><context:annotation-config></context:annotation-config>
<!--加载配置文件--><context:property-placeholder location="data.properties"></context:property-placeholder>
<!--    配置集合、map、properties--><util:list id="list"><value>l1</value><value>l1</value><value>l1</value></util:list><util:set id="set"><value>s1</value><value>s2</value><value>s3</value></util:set><util:map id="map"><entry key="k1" value="v1"></entry><entry key="k2" value="v2"></entry></util:map><util:properties id="properties"><prop key="p1">p</prop><prop key="p2">p2</prop></util:properties>
</beans>

data.properties

age=10
name=lil

配置实例工厂

@Component
public class NetConnInstanceFactory {@Bean("nc")//<bean id="nc" factory-bean="netConnInstanceFactory" factory-method="getNc">public NetConn getNc(){NetConn conn=new NetConn();conn._load();conn._ping();return conn;}}

Autowired和Qualifer

@Component
public class Person1 {
/*
Autowired
按照类型匹配
@Qualifier//按照id匹配*/@Autowired@Qualifier("dog1")//按照id匹配private Dog dog;@Overridepublic String toString() {return "Person1{" +"dog=" + dog +'}';}
}
@Component
public class Dog {
}

HSQDog .java

@Component("dog1")
public class HSQDog extends Dog{
}

当spring容器解析到@Component注解时,创建当前类的bean在spring容器中进行管理,在创建bean的过程中发现了@Autowired注解,会根据当前bean类型,寻找spring中是否存在该类型的bean,找到直接注入,如果找不到还会检查是否有子孙类,实现类存在,如果存在唯一的则自动注入,如果还是没有找到或者找到多个无法注入免责还会按照属性名对应的id去查找对应的bean,如果存在则注入,如果不存在则抛出异常。

其他注解

a.@Scope(value=“prototype”)
修饰类的bean是单例还是多例,默认则是单例
b.@Lazy
配置修饰的类的bean采用懒加载机制
c.@PostConstruct
在对应类中修饰某个方法,将该方法声明为初始化方法,对象创建之后立即执行
@PreDestroy
在bean对应的类中修饰某个方法,将该方法声明为销毁的方法,对象销毁之前调用的方法。

5.6、扩展方式

我们可以通过p和c命名空间

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns=""xmlns:xsi=""xmlns:p=""xmlns:c=""xsi:schemaLocation="://www.springframework.org/schema/beans/spring-beans.xsd"><!--p命名空间注入对应set注入--><bean id="user" class="com.kuangshen.pojo.User" p:name="pcy"></bean><!--必须是有参构造--><bean id="user2" class="com.kuangshen.pojo.User" c:name="pcy2"></bean>
</beans>

6、Bean作用域

6.1、bean定义

在xml配置文件中,Bean需要使用bean标签定义,在创建对象时调用类的无参构造方法,在构造方法重写时默认构造方法不写出来则无法创建对象

属性功能
idBean 实例在 Spring 容器中的唯一标识
classBean 的全限定名称,是包名+类名,指定用来创建对象的类
scope默认值 singleton,表示创建单例对象

6.2、bean的作用域

singleton(默认)将每个 Spring IoC 容器的单个 bean 定义范围限定为单个对象实例。
prototype将单个 bean 定义的作用域限定为任意数量的对象实例。
request将单个 bean 定义的范围限定为单个 HTTP 请求的生命周期。也就是说,每个 HTTP 请求都有一个在单个 bean 定义后面创建的 bean 实例。仅在可感知网络的 Spring ApplicationContext中有效。
session将单个 bean 定义的范围限定为 HTTP Session的生命周期。仅在可感知网络的 Spring ApplicationContext上下文中有效。
application将单个 bean 定义的范围限定为ServletContext的生命周期。仅在可感知网络的 Spring ApplicationContext上下文中有效。
websocket将单个 bean 定义的范围限定为WebSocket的生命周期。仅在可感知网络的 Spring ApplicationContext上下文中有效。

1.单例模式

<bean id="user" class="com.kuangshen.pojo.User" p:name="pcy" scope="singleton"></bean>
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
User user = (User) context.getBean("user");
User user1 = (User) context.getBean("user");
System.out.println(user==user1);

2、原型模式

每创建一个对象都是一个单独的对象

3、其余的只能在web开发中使用

6.3、Bean的生命周期配置

Spring Bean 的生命周期在整个 Spring 中占有很重要的位置,Spring 只帮我们管理Singleton 单例模式 Bean 的完整生命周期,对于 Prototype 多例模式的 Bean,Spring 在创建好交给使用者之后则不会再管理后续的生命周期。

各个状态机

配置编码的 Bean 的生命周期有:初始化、使用、销毁

当一个 Bean 被实例化时,需要执行一些初始化方法,使它转换成可用状态;同样,当一个 Bean 需要销毁,并且从容器中移除时,可能需要做一些清除工作。

**注意:**Bean 是一个可重用组件(常用类),在实际业务中,组件的创建和销毁可能会涉及初始化工作和销毁后的善后工作。比如:我们在创建一个 Dog 对象时需要它先跑起来,在销毁 Dog 对象时,需要它停下来,我们直接使用的就是它在跑的过程中的功能。

为了完成 Bean 的初始化和销毁工作,我们可以在配置中通过 init-method 和destroy-method 属性指定一个方法。

init-method 属性指定一个初始化方法,在实例化时调用该方法;

destroy-method 指定一个销毁方法,在销毁和从容器中移除时调用该方法。

例子:

public class Dog {public Dog() {System.out.println("狗在创建");}public void init(){System.out.println("执行一些初始化工作的操作");}public void work(){System.out.println("狗开始工作");}public void destroy(){System.out.println("让狗停下来休息");}
}

bean.xml

<bean id="dog" class="com.daniu101.model.Dog"  init-method="init" destroy-method="destroy">

test.java

public class Test {public static void main(String[] args) {//从 classpath 中搜索 bean 配置文件ApplicationContext context =new ClassPathXmlApplicationContext("bean.xml");//获取 dog 对象,执行 XML 中配置的初始化方法Dog dog1 = context.getBean("dog",Dog.class);//执行业务方法dog1.work();//关闭 Spring 容器,执行 XML 中配置的销毁方法((ClassPathXmlApplicationContext)context).close();}
}

结果

狗在创建
执行一些初始化工作的操作
狗开始工作
让狗停下来休息

从执行结果我们得知:

Bean 对象创建时执行过程是:调用构造方法、调用 init 方法;

然后根据业务的使用需要,执行的是 work 方法;

当关闭 Spring 时,执行的是:destroy 方法。

后置处理器的重写

增加后置处理器后,调用顺序是:

构造方法,初始化前方法,初始化方法,初始化方法,功能方法,销毁方法;

后置处理器是通过重写实现的,对所有 Bean 有效

MyBeanPostProcessor.java
public class MyBeanPostProcessor implements BeanPostProcessor {public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {System.out.println("BeforeInitialization:"+beanName);return bean;}public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {System.out.println("AfterInitialization:"+beanName);return bean;}
}

bean.xml

<bean id="mybeanpostprocessor"    class="com.daniu101.beanpostprocessor.MyBeanPostProcessor" />

测试结果为:

狗在创建
BeforeInitialization:dog
执行一些初始化工作的操作
AfterInitialization:dog
狗开始工作
让狗停下来休息

7、bean的自动装配

Spring在上下文中自动寻找,并自动装配属性

三种装配方式:

1、在xml中显示装配

1.1byName自动装配

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns=""xmlns:xsi=""xmlns:p=""xmlns:c=""xsi:schemaLocation="://www.springframework.org/schema/beans/spring-beans.xsd"><bean scope="singleton" id="cat" class="com.kuangshen.pojo.Cat"/><bean class="com.kuangshen.pojo.Dog" id="dog" /><!--byName:会自动在容器上下文中寻找,和自己对象set方法后面的值对应的beanid--><bean id="person" class="com.kuangshen.pojo.Person" autowire="byName"><property name="name" value="pcy"/></bean>
</beans>

1.2byType自动装配

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns=""xmlns:xsi=""xmlns:p=""xmlns:c=""xsi:schemaLocation="://www.springframework.org/schema/beans/spring-beans.xsd"><bean scope="singleton" id="cat" class="com.kuangshen.pojo.Cat"/><bean class="com.kuangshen.pojo.Dog" id="dog" /><!--byName:会自动在容器上下文中寻找,和自己对象set方法后面的值对应的beanidbyType:会自动在容器上下文中寻找,和自己对象对象属性类型相同的bean,但是必须保证类型唯一--><bean id="person" class="com.kuangshen.pojo.Person" autowire="byType"><property name="name" value="pcy"/></bean>
</beans>

byname需要保证所有的bean的id唯一,并且这个bean需要和自动注入的属性的set方法的值一致

bytype需要保证所有的bean的class唯一,并且这个bean需要和自动注入的属性的类型一致

2、使用注解自动装配

jdk1.5支持的注解,spring2.5支持的

要使用注解需要:

  • 导入约束 context
  • 配置注解的支持 context:annotation-config/
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns=""xmlns:xsi=""xmlns:context=""xsi:schemaLocation="://www.springframework.org/schema/beans/spring-beans.xsd://www.springframework.org/schema/context/spring-context.xsd"><bean id="cat" class="com.kuangshen.pojo.Cat"/><bean id="dog" class="com.kuangshen.pojo.Dog"/><bean id="person" class="com.kuangshen.pojo.Person"/><context:annotation-config/></beans>
package com.kuangshen.pojo;import org.springframework.beans.factory.annotation.Autowired;/*** @author pcy* @date 2021/2/14 - 18:18*/
public class Person {@Autowiredprivate Cat cat;@Autowiredprivate Dog dog;private String name;@Overridepublic String toString() {return "Person{" +"cat=" + cat +", dog=" + dog +", 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;}public String getName() {return name;}public void setName(String name) {this.name = name;}
}

@Autowired:

  • 可以忽略set方法,前提是这个自动装配的属性在IOC容器中存在,切符合byName

  • 直接在属性上使用即可

  • 也可以在set方式上使用

  • //如果显示的定义了Autowird的require属性为false,说明这个对象可以为null
    @Autowired(required = false)
    private Cat cat;


如果@Autowired自动装配的环境比较复杂,自动装配无法通过一个注解**@Autowired**来完成的时候,我们可以通过@Qualifier来配置,指定唯一一个bean对象

@Autowired
@Qualifier(value = “cat222”)
private Cat cat;
@Autowired
@Qualifier(value = “dog222”)
private Dog dog;

@Nullable:字段标记了这个注解,说明这个字段可以为null## 2、在java中显示装配

@Resource
private Cat cat;
@Resource(name = “dog”)
private Dog dog;
private String name;


```

Resource和Autowired的区别:

都是用来自动装配的,都可以放在属性字段上

Autowired通过byType的方式实现,而且必须要求这个对象存在

Resource默认通过byname的方式实现,如果找不到名字,则通过byType实现,如果两个找不到就会报错

3、隐式自动装配【重要】

8、使用注解开发

在spring4.0之后,必须保证aop的包导入了

使用注解需要导入context约束,增加注解的支持

1、bean

@Component
public class User { public String name;public void setName(String name) {this.name = name;}
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns=""xmlns:xsi=""xmlns:context=""xsi:schemaLocation="://www.springframework.org/schema/beans/spring-beans.xsd://www.springframework.org/schema/context/spring-context.xsd"><context:component-scan base-package="com.kuangshen.pojo"/><context:annotation-config/></beans>

2、属性注解

@Component
public class User {//@Value("kuan")public String name;@Value("kuan")public void setName(String name) {this.name = name;}
}

3、衍生注解

@Component有几个衍生注解
我们在web开发中,会按照mvc三层架构分层
dao			   @Repository
service		@Service
controller	    @Controller
这四个注解功能都是一样的,都是代表将某个类注册到spring容器中,装配bean

4、自动配置注解

5、作用域

@Component
@Scope("singleton")//单例模式
public class User {//@Value("kuan")public String name;@Value("kuan")public void setName(String name) {this.name = name;}
}

6、小结

xml和注解:

xml是万能的,适用于任何场合

注解不是自己类使用不了,维护相对复杂

最佳实践:

xml用来管理bean

注解只负责属性的注入

我们在使用的过程中只需要注意一个问题,必须让注解生效,就需要开启注解的支持

9、完全使用java的配置spring

现在完全不使用spring的xml配置,全交给java来做

javaConfig是Spring的一个子项目,在spring4之后,他成为了一个新功能

配置文件

@Configuration//也会被spring容器中,因为他也死一个@Component.代表这是一个配置类,就和我们之前看的beans.xml一样
@ComponentScan("com.kuangshen.pojo")
@Import(config1.class)
public class config {//注册一个bean,就相当于我们之前写的bean标签//这个方法的名字,就相当于bean标签中的id属性//这个方法的返回值,就相当于bean标签中的class属性@Beanpublic User getUser(){return new User();}
}
@Configuration//也会被spring容器中,因为他也死一个@Component.代表这是一个配置类,就和我们之前看的beans.xml一样
public class config1 {//注册一个bean,就相当于我们之前写的bean标签//这个方法的名字,就相当于bean标签中的id属性//这个方法的返回值,就相当于bean标签中的class属性@Beanpublic User getUser(){return new User();}
}
//这个注解就是说明这个类被spring接管了
@Component
public class User {String name;public String getName() {return name;}@Value("pcy")public void setName(String name) {this.name = name;}
}
public class MyTest {public static void main(String[] args) {ApplicationContext context = new AnnotationConfigApplicationContext(config.class);User user = context.getBean("user",User.class);System.out.println(user.getName());}
}

这种纯java的配置方式,在SpringBoot随处可见!

10、代理模式

中介:帮助一些人做一些事情

为什么要学习代理模式?

因为这是springAOP的底层【SpringAOP和SpringMVC】

代理模式分类:

  • 静态代理
  • 动态代理

什么是代理模式?

10.1、静态代理

角色分析

  • 抽象角色:一般会使用接口或者抽象类来解决
  • 真实角色:被代理的角色
  • 代理角色:代理角色,代理真实角色后我们会做一些附属操作
  • 客户:访问代理对象的人

代理模式的好处:

  • 可以使真实角色的操作更加纯粹,不用关注一些公共的业务
  • 公共也就交给代理角色!实现了业务的分工
  • 公共业务发生扩展的时候,方便集中管理

缺点:

  • 一个真实角色就会产生一个代理角色,开发会变低
public interface Rent {public void rent();
}
public class Host implements Rent {public void rent() {System.out.println("房东要出租房子");}
}
package com.kuangshen.demo01;
public class Proxy implements Rent{Host host;public Proxy(Host host) {this.host = host;}public Proxy() {}public void rent() {host.rent();}//看房public void seeHouse() {System.out.println("看房");}
}
public class Client {public static void main(String[] args) {//房东要租房子Host host=new Host();//代理角色,中介一般会有一些附属操作Proxy proxy = new Proxy(host);//你不用面对房东,直接找中介proxy.rent();proxy.seeHouse();}
}

10.2、加深理解

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("查询了一个用户");}
}
public class UserServiceProxy implements UserService{private UserServiceImpl userService;public UserServiceImpl getUserService() {return userService;}public void setUserService(UserServiceImpl userService) {this.userService = userService;}public void add() {}public void delete() {}public void update() {}public void select() {}
}
public class Client {public static void main(String[] args) {UserServiceImpl userService=new UserServiceImpl();UserServiceProxy userServiceProxy=new UserServiceProxy();userServiceProxy.setUserService(userService);userServiceProxy.add();}
}

10.3、动态代理

动态代理和静态代理角色一样

动态代理的代理类是动态代理是动态生成的,不是我们直接写的

动态代理分为两大类:基于接口的动态代理,基于类的动态代理

  • 基于接口的------JDK动态代理
  • 基于类的:cglib
  • java字节码实现:javasist
package com.kuangshen.demo04;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class ProxyInvocationHander implements InvocationHandler {//被代理的接口private Object target;public void setTarget(Object target) {this.target = target;}//生成得到代理类public Object getProxy(){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);}
}
package com.kuangshen.demo04;import com.kuangshen.demo02.UserService;
import com.kuangshen.demo02.UserServiceImpl;/*** @author pcy* @date 2021/2/15 - 16:27*/
public class Client {public static void main(String[] args) {UserServiceImpl userService = new UserServiceImpl();//代理角色不存在ProxyInvocationHander hander = new ProxyInvocationHander();//设置要处理的对象hander.setTarget(userService);//动态生成代理类UserService proxy = (UserService) hander.getProxy();proxy.delete();}
}

动态代理的好处:

  • 可以使真实角色的操作更加纯粹,不用关注一些公共的业务
  • 公共也就交给代理角色,实现了业务的分工
  • 公共业务发生拓展的时候,方便集中管理
  • 一个动态代理类代理的是一个借口,一般就是对应的一类业务
  • 一个动态代理类可以代理多个类,只要实现了同一个接口就可以

12、整合Mybatis

1、导入相关jar包

<dependencies><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.13</version></dependency><dependency><groupId>mybatis</groupId><artifactId>mybatis</artifactId><version>3.4.5</version></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.47</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-webmvc</artifactId><version>5.3.3</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-jdbc</artifactId><version>5.2.7.RELEASE</version></dependency><dependency><groupId>org.aspectj</groupId><artifactId>aspectjweaver</artifactId><version>1.8.4</version></dependency><dependency><groupId></groupId><artifactId></artifactId></dependency><!-- .mybatis/mybatis-spring --><dependency><groupId>org.mybatis</groupId><artifactId>mybatis-spring</artifactId><version>2.0.6</version></dependency><!-- .springframework/spring-jdbc -->
<dependency><groupId>org.springframework</groupId><artifactId>spring-jdbc</artifactId><version>5.3.3</version>
</dependency>
<!-- .springframework/spring-jdbc -->
<dependency><groupId>org.springframework</groupId><artifactId>spring-jdbc</artifactId><version>5.3.3</version>
</dependency></dependencies>

编写数据源配置

sqlSessionFactory

sqlSessionTemplate

需要给接口加实现类

将自己写的实现类注入到spring中

测试使用

编写一个实体类

public class User {int id;String name;String pwd;@Overridepublic String toString() {return "User{" +"id=" + id +", name='" + name + '\'' +", pwd='" + pwd + '\'' +'}';}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getPwd() {return pwd;}public void setPwd(String pwd) {this.pwd = pwd;}public int getId() {return id;}public void setId(int id) {this.id = id;}public User() {}public User(int id, String name, String pwd) {this.id = id;this.name = name;this.pwd = pwd;}
}

编写接口UserMapper

public interface UserMapper {public List<User> selectUser();
}

编写配置映射文件UserMapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Config 3.0//EN"".dtd">
<mapper namespace="com.kuangshen.dao.UserMapper"><select id="selectUser" resultType="user">select * from user</select>
</mapper>

编写mybatis-config.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configurationPUBLIC "-//mybatis.org//DTD Config 3.0//EN"".dtd">
<configuration><typeAliases><package name="com.kuangshen.pojo"/></typeAliases>
</configuration>

编写spring-dao.xml连接数据源

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns=""xmlns:xsi=""xsi:schemaLocation="://www.springframework.org/schema/beans/spring-beans.xsd"><!--使用DataSource:使用Spring的数据源替换Mybatiss的配置c3p0 dbcp这里我们使用Spring提供的JDBC--><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/mall"/><property name="username" value="root"/><property name="password" value="123456"/></bean><!--sqlSessionFactory--><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/kuangshen/dao/*.xml"/></bean><!--SqlSessionTemplate:就是我们使用的sqlSession--><bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate"><!--因为没有set方法--><constructor-arg index="0" ref="sqlSessionFactory"/></bean><bean id="userMapper" class="com.kuangshen.dao.UserMapperImpl"><property name="sqlSession" ref="sqlSession"/></bean>
</beans>

编写UserMapperImpl实现类

方式一:UserMapperImpl.java

public class UserMapperImpl implements UserMapper {//我们所有的操作,读实用sqlSession来执行,现在都是使用SqlSessionTempleprivate SqlSessionTemplate sqlSession;public void setSqlSession(SqlSessionTemplate sqlSession){this.sqlSession=sqlSession;}public List<User> selectUser() {UserMapper mapper=sqlSession.getMapper(UserMapper.class);return mapper.selectUser();}
}

方式二UserMapperImpl2.java

public class UserMapperImpl2 extends SqlSessionDaoSupport implements UserMapper{public List<User> selectUser() {SqlSession sqlSession = getSqlSession();return getSqlSession().getMapper(UserMapper.class).selectUser();}
}

编写application.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns=""xmlns:xsi=""xsi:schemaLocation="://www.springframework.org/schema/beans/spring-beans.xsd"><import resource="classpath:spring-dao.xml"/><bean id="userMapper" class="com.kuangshen.dao.UserMapperImpl"><property name="sqlSession" ref="sqlSession"/></bean><bean id="userMapper2" class="com.kuangshen.dao.UserMapperImpl2"><property name="sqlSessionFactory" ref="sqlSessionFactory"/></bean>
</beans>

编写测试类

public class Test {@org.junit.Testpublic void test(){ApplicationContext context = new ClassPathXmlApplicationContext("application.xml");UserMapper userMapper = context.getBean("userMapper", UserMapper.class);for (User userMappers:userMapper.selectUser()){System.out.println(userMappers);}}
}

13、声明式事务

要么都成功,要么都失败

事务在项目中十分重要,涉及到数据的一致性问题

把一组业务当成一个业务来做

确保完整性和一致性

事务ACID原则:

  • 原子性:要么都成功,要么都失败

  • 一致性:保持一致性

  • 隔离性:多个业务可能操作同一个资源,防止数据损坏

  • 持久性:事务一旦完成了,无论系统发生什么问题,结果都不会被影响,被持久化的写到存储器中

1、spring中的事务管理

声明式事务:AOP

编程式事务:需要在代码中,进行事务管理

思考:为什么需要事务?

  • 如果不配置事务,可能需要数据提交不一致的情况下;
  • 如果我们不在spring中去配置声明式事务,我们就需要在代码中手动配置事务
  • 事务在项目的开发中十分重要,涉及到数据的一致性。

实体类

public class User {int id;String name;String pwd;@Overridepublic String toString() {return "User{" +"id=" + id +", name='" + name + '\'' +", pwd='" + pwd + '\'' +'}';}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getPwd() {return pwd;}public void setPwd(String pwd) {this.pwd = pwd;}public int getId() {return id;}public void setId(int id) {this.id = id;}public User() {}public User(int id, String name, String pwd) {this.id = id;this.name = name;this.pwd = pwd;}
}

接口

public interface UserMapper {public List<User> selectUser();//添加一个用户int addUser(User user);//删除一个用户int deleteUser(int id);
}

UserMapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Config 3.0//EN"".dtd">
<mapper namespace="com.kuangshen.dao.UserMapper"><select id="selectUser" resultType="user">select * from user</select><insert id="addUser" parameterType="user">insert into user(id,name,pwd) values(#{id},#{name},#{pwd})</insert><delete id="deleteUser" parameterType="int">delete from user where id=#{id}</delete>
</mapper>

UserMapperImpl2.java

public class UserMapperImpl2 extends SqlSessionDaoSupport implements UserMapper{public List<User> selectUser() {User user=new User(2,"u","12");SqlSession sqlSession = getSqlSession();UserMapper mapper = sqlSession.getMapper(UserMapper.class);mapper.addUser(user);mapper.deleteUser(1);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);}
}

mybatis-config.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configurationPUBLIC "-//mybatis.org//DTD Config 3.0//EN"".dtd">
<configuration><typeAliases><package name="com.kuangshen.pojo"/></typeAliases>
</configuration>

spring-dao.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns=""xmlns:xsi=""xmlns:aop=""xmlns:tx=""xsi:schemaLocation="://www.springframework.org/schema/beans/spring-beans.xsd://www.springframework.org/schema/aop/spring-aop.xsd://www.springframework.org/schema/aop/spring-tx.xsd"><!--使用DataSource:使用Spring的数据源替换Mybatiss的配置c3p0 dbcp这里我们使用Spring提供的JDBC--><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/mall"/><property name="username" value="root"/><property name="password" value="123456"/></bean><!--sqlSessionFactory--><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/kuangshen/dao/*.xml"/></bean><!--SqlSessionTemplate:就是我们使用的sqlSession--><bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate"><!--因为没有set方法--><constructor-arg index="0" ref="sqlSessionFactory"/></bean><!--配置声明式事务--><bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><!--<constructor-arg ref="dataSource" />--><property name="dataSource" ref="dataSource"/></bean><!--结合aop实现事务的织入--><!--配置事务通知--><tx:advice id="txAdvice" transaction-manager="transactionManager"><!--给那些方法配置事务--><!--p配置事务的传播特性:new  默认:REQUIREDread-only:只读--><tx:attributes><tx:method name="add" propagation="REQUIRED"/><tx:method name="update" propagation="REQUIRED"/><tx:method name="query" read-only="true"/><tx:method name="*" propagation="REQUIRED"/><tx:method name="delete" propagation="REQUIRED"/></tx:attributes></tx:advice><aop:config><aop:pointcut id="txPocut" expression="execution(* com.kuangshen.dao.*.*(..))"/><aop:advisor advice-ref="txAdvice" pointcut-ref="txPocut"/></aop:config>
</beans>

application.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns=""xmlns:xsi=""xsi:schemaLocation="://www.springframework.org/schema/beans/spring-beans.xsd"><import resource="classpath:spring-dao.xml"/><bean id="userMapper2" class="com.kuangshen.dao.UserMapperImpl2"><property name="sqlSessionFactory" ref="sqlSessionFactory"/></bean>
</beans>

测试:

public class Test {@org.junit.Testpublic void test(){ApplicationContext context = new ClassPathXmlApplicationContext("application.xml");UserMapper userMapper = context.getBean("userMapper2", UserMapper.class);for (User userMappers:userMapper.selectUser()){System.out.println(userMappers);}}
}

pom.xml依赖配置

<properties><spring.version>5.2.3.RELEASE</spring.version>
</properties>
<dependency><groupId>org.springframework</groupId><artifactId>spring-core</artifactId><version>${spring.version}</version>
</dependency>
<dependency><groupId>org.springframework</groupId><artifactId>spring-web</artifactId><version>${spring.version}</version>
</dependency>
<dependency><groupId>org.springframework</groupId><artifactId>spring-oxm</artifactId><version>${spring.version}</version>
</dependency>
<dependency><groupId>org.springframework</groupId><artifactId>spring-tx</artifactId><version>${spring.version}</version>
</dependency>
<dependency><groupId>org.springframework</groupId><artifactId>spring-jdbc</artifactId><version>${spring.version}</version>
</dependency>
<dependency><groupId>org.springframework</groupId><artifactId>spring-webmvc</artifactId><version>${spring.version}</version>
</dependency>
<dependency><groupId>org.springframework</groupId><artifactId>spring-aop</artifactId><version>${spring.version}</version>
</dependency>
<dependency><groupId>org.springframework</groupId><artifactId>spring-context-support</artifactId><version>${spring.version}</version>
</dependency>
<dependency><groupId>org.springframework</groupId><artifactId>spring-test</artifactId><version>${spring.version}</version>
</dependency>

2021-6-23-------------01-1spring----IOC

01-1spring---IOC

  • 1、简介
    • 1.2、优点
    • 1.3、组成
    • 1.4、拓展
  • 2、IOC理论推导
  • 3.IOC获取对象的方式
  • 4、IOC创建对象的方式
    • (1)通过类的无参构造方法来创建对象
    • (2)通过指定的构造器来创建对象
    • (3)通过工厂创建对象
      • i.通过静态工厂创建对象
      • ii通过实例工厂创建对象
      • iii.spring工厂创建对象
  • 4、spring配置
    • 4.1、别名
    • 4.2、Bean配置
      • a单例和多例
        • 单例模式的生命周期:
        • 多例模式生命周期
      • b.懒加载机制
      • d. 方法的创建和销毁
      • c.别名
    • 4.3、import
  • 5、DI依赖注入
    • 5.0三个概念
      • 元数据的作用
      • 配置元数据的方式:
    • 5-0、两类容器
      • 第一种:BeanFactory接口的XmlBeanFactory实现类//过时
      • 第二种:ApplicationContext实现类
    • 5.1构造器注入
    • 5.2、通过set方式注入(普通属性的注入)
    • 5.3、集合的注入方式注入
    • 5.4自动装配的注入
    • 5.5、注解方式
    • 注解属性值
    • 配置实例工厂
    • Autowired和Qualifer
      • 其他注解
    • 5.6、扩展方式
  • 6、Bean作用域
    • 6.1、bean定义
    • 6.2、bean的作用域
      • 1.单例模式
      • 2、原型模式
      • 3、其余的只能在web开发中使用
    • 6.3、Bean的生命周期配置
      • 各个状态机
      • 后置处理器的重写
  • 7、bean的自动装配
    • 1、在xml中显示装配
      • 1.1byName自动装配
      • 1.2byType自动装配
    • 2、使用注解自动装配
    • 3、隐式自动装配【重要】
  • 8、使用注解开发
    • 1、bean
    • 2、属性注解
    • 3、衍生注解
    • 4、自动配置注解
    • 5、作用域
    • 6、小结
  • 9、完全使用java的配置spring
  • 10、代理模式
    • 10.1、静态代理
    • 10.2、加深理解
    • 10.3、动态代理
  • 12、整合Mybatis
    • 1、导入相关jar包
    • 编写一个实体类
    • 编写接口UserMapper
    • 编写配置映射文件UserMapper.xml
    • 编写mybatis-config.xml
    • 编写spring-dao.xml连接数据源
    • 编写UserMapperImpl实现类
    • 编写application.xml
    • 编写测试类
  • 13、声明式事务
    • 实体类
    • 接口
    • UserMapper.xml
    • UserMapperImpl2.java
    • mybatis-config.xml
    • spring-dao.xml
    • application.xml
    • 测试:
  • pom.xml依赖配置

1、简介

2002年,首次推出了spring框架的的雏形,interface21框架

2004年,以interface21为基础,经过重新设计,并且不断丰富其内涵,于2004年发布了1.0版本

spring理念:使现有的技术更加容易使用,整合了现有的技术

SSH:struts2+spring+Hibernate

SSM:SpringMVC+Spring+Mybatis

中文文档:.1.3.RELEASE/reference.

// A code block
<!-- .springframework/spring-webmvc -->
<dependency><groupId>org.springframework</groupId><artifactId>spring-webmvc</artifactId><version>5.3.3</version>
</dependency>
<!-- .springframework/spring-jdbc -->
<dependency><groupId>org.springframework</groupId><artifactId>spring-jdbc</artifactId><version>5.3.3</version>
</dependency>

1.2、优点

  • spring是一个免费的开源框架
  • spring是一个轻量级的、非入侵式的框架
  • 控制反转(IOC),面向切面编程(AOP)
  • 支持事务的处理对框架整合的支持

总结:spring是一个轻量级的控制反转和面向切面编程的框架

1.3、组成

1.4、拓展

现代化开发:基于spring开发

springboot

  • 一个快速开发的脚手架
  • 基于springboot可以快速开发单个微服务

Spring Cloud

  • 基于springBoot实现的

大多数公司都使用springboot进行快速开发,学习springboot前提,需要完全掌握spring和springmvc

spring的弊端:

发展了太久,违背了原来的理念,配置十分繁琐,配置地狱

2、IOC理论推导

Ioc概念:控制反转,Inversion of Control

控制:对象控制——-spring控制

反转:spring设置对象、其他资源


在初始化一个spring容器时,spring会解析指定的xml文件,当解析到其中的bean标签时,会根据该标签中class属性指定的类的全路径名,通过反射来创建该类的对象,并将对象存入内置的map中管理,其中键就是该标签的id,值就是对象。
之后,当通过getbean方法来从容器中获取对象时其实就是根据传入的条件在内置的map中寻找是否有匹配的兼职,如果有则将键值对中保存的对象返回,如果没有就抛出异常。


对象由spring创建和管理

1、UserDao

// A code block
public interface UserDao {void getUser();
}

2、UserDaoImpl

public class UserDaoImpl implements UserDao{@Overridepublic void getUser() {System.out.println("实现了接口");}
}
public class UserDaoMysqlImpl implements UserDao{@Overridepublic void getUser() {System.out.println("实现了mysql");}
}

3、UserService业务接口

public interface UserService {void getUser();
}

4、UserServiceImpl业务实现类

​ //利用set方法实现了动态注入

public class UserServiceImpl implements UserService{UserDao userDao;//利用set方法实现了动态注入public void setUserDao(UserDao userDao) {this.userDao = userDao;}@Overridepublic void getUser() {userDao.getUser();}
}
public class Test {public static void main(String[] args) {UserService userService=new UserServiceImpl();((UserServiceImpl) userService).setUserDao(new UserDaoMysqlImpl());userService.getUser();}
}

之前,程序是主动创建对象,控制权在程序员手上

使用了set注入后程序员不再有主动性,而是变成了被动接受对象!

这种思想从本质上解决了问题,我们程序员不用再管理对象的创建了。系统的耦合性大大降低,可以更加专注在业务的实现上,这是IOC的核心原理
xml


<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns=""xmlns:xsi=""xsi:schemaLocation="://www.springframework.org/schema/beans/spring-beans.xsd"><!--使用spring创建对象,在spring中这些都称为Bean--><bean id="UserDaoImpl" class="com.kuangshen.dao.UserDaoImpl"/><bean id="UserDaoMysqlImpl" class="com.kuangshen.dao.UserDaoMysqlImpl"/><bean id="UserServiceImpl" class="com.kuangshen.service.UserServiceImpl"><!--ref :引用Spring容器中创建好的对象--><property name="userDao" ref="UserDaoImpl"/></bean></beans>

控制反转

概念:
控制反转就是将对象的创建和生命周期的管理过程交给spring去处理,从此开发中不需要关注对象的创建和生命周期的管理,而是在需要时由spring来提供。

DI:在创建对象的过程中spring可以依据配置对对象的属性进行设置

  • 是一种思想,DI(依赖注入)实现IOC的一种方法,没有IOC的程序中我们使用面向对象编程
  • 获得依赖对象的方式反转了。

采用XML的配置Bean的时候,Bean的定义信息是和实现是分离的。而采用注解的方式可以把两者合为一体,Bean的信息直接以注解的形式定义在实现类里面,从而达到零配置的目的。

package com.kuangshen.pojo;/*** @author pcy* @date 2021/2/14 - 15:29*/
public class Hello {private String str;public String getStr() {return str;}//必须有set方法public void setStr(String str) {this.str = str;}@Overridepublic String toString() {return "Hello{" +"str='" + str + '\'' +'}';}
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns=""xmlns:xsi=""xsi:schemaLocation="://www.springframework.org/schema/beans/spring-beans.xsd"><!--使用spring创建对象,在spring中这些都称为Bean--><bean id="hello" class="com.kuangshen.pojo.Hello"><property name="str" value="Spring"/></bean></beans>
import com.kuangshen.pojo.Hello;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;/*** @author pcy* @date 2021/2/14 - 15:38*/
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());}
}

3.IOC获取对象的方式

1).通过id获取bean
2).通过class来获取bean

@Testpublic void eatTest(){//初始化容器ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");/*** 通过id获取bean*/
//        Person person = (Person) context.getBean("Person");
/*** 通过class来获取bean*/Person per = context.getBean(Person.class);ClassPathXmlApplicationContext context1 = (ClassPathXmlApplicationContext) context;context1.close();}

4、IOC创建对象的方式

(1)通过类的无参构造方法来创建对象

Person.java

public class Person {public void eat(){System.out.println("人们在吃饭");}
}

applicationContext.xml

<!--推论1:不能配置多个id相同的bean推论2:可以配置多个类相同,但是id不同的bean推论3:不能配置多个id相同的bean--><bean id="com.pcy.Person" class="com.pcy.Person"></bean>

(2)通过指定的构造器来创建对象

public Person(String name,int age) {System.out.println("name:"+name+",age:"+age);}

applicationContext.xml

<bean id="person" class="com.pcy.Person" scope="singleton" lazy-init="true">
<!--
index:代表第几个参数
name:什么名字的参数
type:参数类型
value和ref:
value:引用类型或者是String类型
ref:赋予值(引用数据类型)
index、name、type不需要都设置,只要没有歧义就可以了
--><constructor-arg index="0" value="lili"/><constructor-arg index="1" value="10"/></bean>

(3)通过工厂创建对象

如果创建对象需要若干设置后才能使用,spring就可以通过工厂类将创建对象的细节封装

i.通过静态工厂创建对象

NetConn.java

public class NetConn {public void _login(){System.out.println("正在登陆");}public void _index(){System.out.println("验证密码");}public void _sendData(){System.out.println("发送数据");}
}

NetConnFactory .java

public class NetConnFactory {private NetConnFactory(){}public static NetConn getNc(){NetConn conn=new NetConn();conn._index();conn._login();return conn;}}
<bean id="netConnFactory" class="com.pcy.NetConnFactory" factory-method="getNc">

原理图

ii通过实例工厂创建对象

NetConnInstanceFactory.java

public class NetConnInstanceFactory {public NetConn getNc(){NetConn conn=new NetConn();conn._index();conn._login();return conn;}
}
  <bean id="netConnInstanceFactory" class="com.pcy.NetConnInstanceFactory"></bean><bean id="net" factory-bean="netConnInstanceFactory" factory-method="getNc"></bean>

iii.spring工厂创建对象

spring内置接口FactoryBean,也可以实现这个接口来开发spring工厂目标类
NetConnSpringFactory .java

public class NetConnSpringFactory implements FactoryBean<NetConn>{@Overridepublic NetConn getObject() throws Exception {NetConn netConn=new NetConn();netConn._login();netConn._index();return netConn;}/*** 获取目标对象类型的方法* @return*/@Overridepublic Class<?> getObjectType() {return NetConn.class;}//控制对象是否是单例@Overridepublic boolean isSingleton() {return false;}
}

applicationContext.xml

        <bean id="netSpringFactory" class="com.pcy.NetConnSpringFactory"></bean>

总结:在配置文件加载的时候,容器中管理的对象就已经初始化了。

4、spring配置

4.1、别名

<!--别名:如果添加了别名也可以通过别名来获取对象-->
<alias name="user" alias="user2"/>

4.2、Bean配置

a单例和多例

spring在默认情况下是单例的,一个bean只会创建一个对象,无论创建多少个对象都返回的是一个对象
优点:减少了对象的创建,从而减少内存的消耗

<bean id="person" class="com.pcy.Person" scope="singleton"></bean>

在实际开发中是存在多例的需求的,所以bean有多例模式

<bean id="person" class="com.pcy.Person" scope="prototype"></bean>

单例模式的生命周期:

spring在启动时,解析xml发现bean标签后,直接创建该bean对象存入map的内部,无论调用多少次getBean都是该bean从map中获取对象返回,一直是一个对象,一直被spring容器持有,直到容器退出

多例模式生命周期

spring容器启动时,发现该bean进行管理,并不会创建对象,此后每次使用geBean都是重新创建该对象返回,每次都是一个新的对象,这个对象spring容器并不会被spring容器持有,什么时候销毁取决于用户。

b.懒加载机制

spring容器初始化的过程中,解析xml,并将单例的bean创建并保存到map中,这样的机制在bean比较少时问题不大,一旦bean非常多时,spring会花费大量的时间创建bean,大量的空间存储bean,所以spring提供了懒加载机制。
懒加载机制:
可以规定bean在spring启动时不立即创建,而是在后续使用的时候才创建

注意
只对单例bean标签使用,因为多例本身是懒加载
单例bean标签使用懒加载之后还是单例

        <bean id="person" class="com.pcy.Person" scope="prototype" lazy-init="true">

全局懒加载

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns=""xmlns:xsi=""xsi:schemaLocation=" .xsd"default-lazy-init="true">
</beans>

如果同时设定全局和指定bean懒加载机制,且配置不相同,则对于该bean局部配置覆盖全局配置

d. 方法的创建和销毁

ProDao.java

public class ProDao {public ProDao() {System.out.println("ProdDao 被创建。。。");}public void init(){System.out.println("init。。连接数据库。。。。。");}public void destory(){System.out.println("destory。。断开数据库。。。。。");}public void  addProd(){System.out.println("增加商品。。");}public void  updateProd(){System.out.println("修改商品。。");}public void  delProd(){System.out.println("删除商品。。");}public void  queryProd(){System.out.println("查询商品。。");}}
<bean id="prodao" class="com.pcy.ProDao" init-method="init" destroy-method="destory"></bean>

c.别名

<!--id:bean的唯一标识符,也就是相当于我们学过的对象名class:bean对象所对应的全限定名name:也是别名,而且Name更加高级,可以同时多个别名,或者用空格分隔,或者用逗号分隔--><bean id="user" class="com.kuangshen.pojo.User" name="user3 u2" scope="prototype"><constructor-arg name="name" value="wang"/></bean>

4.3、import

一般用于团队开发使用,他可以将多个配置文件导入合并为一个

<import resource="applicationContext.xml"/>

使用的时候直接使用一个总的就可以了

5、DI依赖注入

在对象创建时操作其属性

5.0三个概念

依赖:组件之间的关系依赖

注入:注入某个类所依赖的组件,告诉spring如何创建管理对象

元数据:媒体数据,中间数据,就是告诉spring如何创建管理时所说的话

元数据的作用

spring通过元数据提供的指令(配置),容器知道对那些对象进行实例化,配置和组装。

配置元数据的方式:

xml,注解,代码

5-0、两类容器

第一种:BeanFactory接口的XmlBeanFactory实现类//过时

XmlBeanFactory factory = new XmlBeanFactory(new ClassPathResource("bean.xml"));

第二种:ApplicationContext实现类

//第一种实现类
//绝对路径	
//该容器从 XML 文件中加载已被定义的 Bean,需 要给构造器提供完整的路径
ApplicationContext context = new FileSystemXmlApplicationContext("");
//从 classpath 中搜索 bean 配置文件
//该容器从 XML 文件中加载已被定义的 Bean,不
需要提供完整路径,只需正确配置 classpath 下的文件名称即可,因为容器会从
classpath 中搜索 bean 配置文件,classpath 是编译后的 class 文件所在路径ApplicationContext context =new 
ClassPathXmlApplicationContext("SpringBeans.xml");

5.1构造器注入

5.2、通过set方式注入(普通属性的注入)

依赖注入:set注入

依赖:bean对象的创建依赖于容器

注入:bean对象中的所有属性,由容器来注入

package com.kuangshen.pojo;import java.util.*;/*** @author pcy* @date 2021/2/14 - 17:19*/
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;@Overridepublic String toString() {return "Student{" +"name='" + name + '\'' +", address=" + address +", books=" + Arrays.toString(books) +", hobbys=" + hobbys +", card=" + card +", games=" + games +", wife='" + wife + '\'' +", info=" + 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;}
}
package com.kuangshen.pojo;/*** @author pcy* @date 2021/2/14 - 17:20*/
public class Address {private String address;public String getAddress() {return address;}public void setAddress(String address) {this.address = address;}public Address(String address) {this.address = address;}
}
<bean id="student" class="com.kuangshen.pojo.Student"><!--第一种--><property name="name" value="pcy"/></bean>

5.3、集合的注入方式注入

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns=""xmlns:xsi=""xsi:schemaLocation="://www.springframework.org/schema/beans/spring-beans.xsd"><bean id="student" class="com.kuangshen.pojo.Student"><!--第一种--><property name="name" value="pcy"/><!--第二种:bean注入 ref注入--><property name="address" ref="address"/><!--数组的注入--><property name="books"><array><value>d</value><value>y</value><value>s</value></array></property><!--list注入--><property name="hobbys"><list><value>d</value><value>y</value><value>s</value></list></property><!--map--><property name="card"><map><entry key="身份证" value="wsssds"/><entry key="银行卡" value="2343"/></map></property><!--set--><property name="games"><set><value>s</value><value>d</value></set></property><!--prop注入--><property name="info"><props><prop key="12">xin</prop><prop key="13">lihai</prop></props></property><!--null值--><property name="wife"><null/></property></bean><bean id="address" class="com.kuangshen.pojo.Address"><property name="address" value="西安"/></bean>
</beans>

5.4自动装配的注入

全局装配和局部装配

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns=""xmlns:xsi=""xsi:schemaLocation=" .xsd"default-lazy-init="true"default-autowire="byName">
<!--    全局装配-->
<!--    自动装配
byName:遇到要注入的自定义bean类型数据时,按照bean的属性名来同名的id的bean来进行注入
如果找不到就不会注入,返回的值是null
byType:按照bean的类型来找同类型的bean来进行注入
--><bean id="person" class="com.pcy.Person" autowire="byName"></bean><bean id="dog" class="com.pcy.Dog"><property name="name" value="丽丽"></property><property name="age" value="10"></property></bean>
</beans>

5.5、注解方式

  • 加入spring-aop的jar包
  • 并且加入消息头使得注解生效
    applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns=""xmlns:context=""xmlns:xsi=""xsi:schemaLocation="://www.springframework.org/schema/beans/spring-beans-3.2.xsd://www.springframework.org/schema/context/spring-context-3.2.xsd">
<!--    配置包扫描-->
<!--    注解方式实现IOC,
id:推断准则,如果明确指定id,则采用指定的id
如果没有指定的id,则自动推断id
自动推断id的规则
看类名第二个字母,如果第二个字母是小写,则首字母也小写为id
--><context:component-scan base-package="com.pcy.domain"/>

Person.java

@Component("person")//<bean id="person">
public class Person {
}

注解属性值

@Component("person")//<bean id="person">
public class Person {@Autowiredprivate Dog dog;//@Value("丽丽")//加载配置文件的读取方式@Value("${name}")private String name;@Value("${age}")private int age;//读取集合,map,properties等@Value("#{@list}")private List<String> list;@Value("#{@set}")private Set<String> set;@Value("#{@map}")private Map<String,String> map;@Value("#{@properties}")private Properties properties;@Overridepublic String toString() {return "Person1{" +"name='" + name + '\'' +", age=" + age +", list=" + list +", set=" + set +", map=" + map +", properties=" + properties +'}';}
}

applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns=""xmlns:context=""xmlns:xsi="" xmlns:util=""xsi:schemaLocation="://www.springframework.org/schema/beans/spring-beans-3.2.xsd://www.springframework.org/schema/context/spring-context-3.2.xsd  .xsd"><!--    配置包扫描-->
<!--    注解方式实现IOC,
id:推断准则,如果明确指定id,则采用指定的id
如果没有指定的id,则自动推断id
自动推断id的规则
看类名第二个字母,如果第二个字母是小写,则首字母也小写为id
--><context:component-scan base-package="com.pcy.domain"/><!--    开启注解方式的DI,支持DI以注解方式来注入数据--><context:annotation-config></context:annotation-config>
<!--加载配置文件--><context:property-placeholder location="data.properties"></context:property-placeholder>
<!--    配置集合、map、properties--><util:list id="list"><value>l1</value><value>l1</value><value>l1</value></util:list><util:set id="set"><value>s1</value><value>s2</value><value>s3</value></util:set><util:map id="map"><entry key="k1" value="v1"></entry><entry key="k2" value="v2"></entry></util:map><util:properties id="properties"><prop key="p1">p</prop><prop key="p2">p2</prop></util:properties>
</beans>

data.properties

age=10
name=lil

配置实例工厂

@Component
public class NetConnInstanceFactory {@Bean("nc")//<bean id="nc" factory-bean="netConnInstanceFactory" factory-method="getNc">public NetConn getNc(){NetConn conn=new NetConn();conn._load();conn._ping();return conn;}}

Autowired和Qualifer

@Component
public class Person1 {
/*
Autowired
按照类型匹配
@Qualifier//按照id匹配*/@Autowired@Qualifier("dog1")//按照id匹配private Dog dog;@Overridepublic String toString() {return "Person1{" +"dog=" + dog +'}';}
}
@Component
public class Dog {
}

HSQDog .java

@Component("dog1")
public class HSQDog extends Dog{
}

当spring容器解析到@Component注解时,创建当前类的bean在spring容器中进行管理,在创建bean的过程中发现了@Autowired注解,会根据当前bean类型,寻找spring中是否存在该类型的bean,找到直接注入,如果找不到还会检查是否有子孙类,实现类存在,如果存在唯一的则自动注入,如果还是没有找到或者找到多个无法注入免责还会按照属性名对应的id去查找对应的bean,如果存在则注入,如果不存在则抛出异常。

其他注解

a.@Scope(value=“prototype”)
修饰类的bean是单例还是多例,默认则是单例
b.@Lazy
配置修饰的类的bean采用懒加载机制
c.@PostConstruct
在对应类中修饰某个方法,将该方法声明为初始化方法,对象创建之后立即执行
@PreDestroy
在bean对应的类中修饰某个方法,将该方法声明为销毁的方法,对象销毁之前调用的方法。

5.6、扩展方式

我们可以通过p和c命名空间

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns=""xmlns:xsi=""xmlns:p=""xmlns:c=""xsi:schemaLocation="://www.springframework.org/schema/beans/spring-beans.xsd"><!--p命名空间注入对应set注入--><bean id="user" class="com.kuangshen.pojo.User" p:name="pcy"></bean><!--必须是有参构造--><bean id="user2" class="com.kuangshen.pojo.User" c:name="pcy2"></bean>
</beans>

6、Bean作用域

6.1、bean定义

在xml配置文件中,Bean需要使用bean标签定义,在创建对象时调用类的无参构造方法,在构造方法重写时默认构造方法不写出来则无法创建对象

属性功能
idBean 实例在 Spring 容器中的唯一标识
classBean 的全限定名称,是包名+类名,指定用来创建对象的类
scope默认值 singleton,表示创建单例对象

6.2、bean的作用域

singleton(默认)将每个 Spring IoC 容器的单个 bean 定义范围限定为单个对象实例。
prototype将单个 bean 定义的作用域限定为任意数量的对象实例。
request将单个 bean 定义的范围限定为单个 HTTP 请求的生命周期。也就是说,每个 HTTP 请求都有一个在单个 bean 定义后面创建的 bean 实例。仅在可感知网络的 Spring ApplicationContext中有效。
session将单个 bean 定义的范围限定为 HTTP Session的生命周期。仅在可感知网络的 Spring ApplicationContext上下文中有效。
application将单个 bean 定义的范围限定为ServletContext的生命周期。仅在可感知网络的 Spring ApplicationContext上下文中有效。
websocket将单个 bean 定义的范围限定为WebSocket的生命周期。仅在可感知网络的 Spring ApplicationContext上下文中有效。

1.单例模式

<bean id="user" class="com.kuangshen.pojo.User" p:name="pcy" scope="singleton"></bean>
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
User user = (User) context.getBean("user");
User user1 = (User) context.getBean("user");
System.out.println(user==user1);

2、原型模式

每创建一个对象都是一个单独的对象

3、其余的只能在web开发中使用

6.3、Bean的生命周期配置

Spring Bean 的生命周期在整个 Spring 中占有很重要的位置,Spring 只帮我们管理Singleton 单例模式 Bean 的完整生命周期,对于 Prototype 多例模式的 Bean,Spring 在创建好交给使用者之后则不会再管理后续的生命周期。

各个状态机

配置编码的 Bean 的生命周期有:初始化、使用、销毁

当一个 Bean 被实例化时,需要执行一些初始化方法,使它转换成可用状态;同样,当一个 Bean 需要销毁,并且从容器中移除时,可能需要做一些清除工作。

**注意:**Bean 是一个可重用组件(常用类),在实际业务中,组件的创建和销毁可能会涉及初始化工作和销毁后的善后工作。比如:我们在创建一个 Dog 对象时需要它先跑起来,在销毁 Dog 对象时,需要它停下来,我们直接使用的就是它在跑的过程中的功能。

为了完成 Bean 的初始化和销毁工作,我们可以在配置中通过 init-method 和destroy-method 属性指定一个方法。

init-method 属性指定一个初始化方法,在实例化时调用该方法;

destroy-method 指定一个销毁方法,在销毁和从容器中移除时调用该方法。

例子:

public class Dog {public Dog() {System.out.println("狗在创建");}public void init(){System.out.println("执行一些初始化工作的操作");}public void work(){System.out.println("狗开始工作");}public void destroy(){System.out.println("让狗停下来休息");}
}

bean.xml

<bean id="dog" class="com.daniu101.model.Dog"  init-method="init" destroy-method="destroy">

test.java

public class Test {public static void main(String[] args) {//从 classpath 中搜索 bean 配置文件ApplicationContext context =new ClassPathXmlApplicationContext("bean.xml");//获取 dog 对象,执行 XML 中配置的初始化方法Dog dog1 = context.getBean("dog",Dog.class);//执行业务方法dog1.work();//关闭 Spring 容器,执行 XML 中配置的销毁方法((ClassPathXmlApplicationContext)context).close();}
}

结果

狗在创建
执行一些初始化工作的操作
狗开始工作
让狗停下来休息

从执行结果我们得知:

Bean 对象创建时执行过程是:调用构造方法、调用 init 方法;

然后根据业务的使用需要,执行的是 work 方法;

当关闭 Spring 时,执行的是:destroy 方法。

后置处理器的重写

增加后置处理器后,调用顺序是:

构造方法,初始化前方法,初始化方法,初始化方法,功能方法,销毁方法;

后置处理器是通过重写实现的,对所有 Bean 有效

MyBeanPostProcessor.java
public class MyBeanPostProcessor implements BeanPostProcessor {public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {System.out.println("BeforeInitialization:"+beanName);return bean;}public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {System.out.println("AfterInitialization:"+beanName);return bean;}
}

bean.xml

<bean id="mybeanpostprocessor"    class="com.daniu101.beanpostprocessor.MyBeanPostProcessor" />

测试结果为:

狗在创建
BeforeInitialization:dog
执行一些初始化工作的操作
AfterInitialization:dog
狗开始工作
让狗停下来休息

7、bean的自动装配

Spring在上下文中自动寻找,并自动装配属性

三种装配方式:

1、在xml中显示装配

1.1byName自动装配

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns=""xmlns:xsi=""xmlns:p=""xmlns:c=""xsi:schemaLocation="://www.springframework.org/schema/beans/spring-beans.xsd"><bean scope="singleton" id="cat" class="com.kuangshen.pojo.Cat"/><bean class="com.kuangshen.pojo.Dog" id="dog" /><!--byName:会自动在容器上下文中寻找,和自己对象set方法后面的值对应的beanid--><bean id="person" class="com.kuangshen.pojo.Person" autowire="byName"><property name="name" value="pcy"/></bean>
</beans>

1.2byType自动装配

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns=""xmlns:xsi=""xmlns:p=""xmlns:c=""xsi:schemaLocation="://www.springframework.org/schema/beans/spring-beans.xsd"><bean scope="singleton" id="cat" class="com.kuangshen.pojo.Cat"/><bean class="com.kuangshen.pojo.Dog" id="dog" /><!--byName:会自动在容器上下文中寻找,和自己对象set方法后面的值对应的beanidbyType:会自动在容器上下文中寻找,和自己对象对象属性类型相同的bean,但是必须保证类型唯一--><bean id="person" class="com.kuangshen.pojo.Person" autowire="byType"><property name="name" value="pcy"/></bean>
</beans>

byname需要保证所有的bean的id唯一,并且这个bean需要和自动注入的属性的set方法的值一致

bytype需要保证所有的bean的class唯一,并且这个bean需要和自动注入的属性的类型一致

2、使用注解自动装配

jdk1.5支持的注解,spring2.5支持的

要使用注解需要:

  • 导入约束 context
  • 配置注解的支持 context:annotation-config/
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns=""xmlns:xsi=""xmlns:context=""xsi:schemaLocation="://www.springframework.org/schema/beans/spring-beans.xsd://www.springframework.org/schema/context/spring-context.xsd"><bean id="cat" class="com.kuangshen.pojo.Cat"/><bean id="dog" class="com.kuangshen.pojo.Dog"/><bean id="person" class="com.kuangshen.pojo.Person"/><context:annotation-config/></beans>
package com.kuangshen.pojo;import org.springframework.beans.factory.annotation.Autowired;/*** @author pcy* @date 2021/2/14 - 18:18*/
public class Person {@Autowiredprivate Cat cat;@Autowiredprivate Dog dog;private String name;@Overridepublic String toString() {return "Person{" +"cat=" + cat +", dog=" + dog +", 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;}public String getName() {return name;}public void setName(String name) {this.name = name;}
}

@Autowired:

  • 可以忽略set方法,前提是这个自动装配的属性在IOC容器中存在,切符合byName

  • 直接在属性上使用即可

  • 也可以在set方式上使用

  • //如果显示的定义了Autowird的require属性为false,说明这个对象可以为null
    @Autowired(required = false)
    private Cat cat;


如果@Autowired自动装配的环境比较复杂,自动装配无法通过一个注解**@Autowired**来完成的时候,我们可以通过@Qualifier来配置,指定唯一一个bean对象

@Autowired
@Qualifier(value = “cat222”)
private Cat cat;
@Autowired
@Qualifier(value = “dog222”)
private Dog dog;

@Nullable:字段标记了这个注解,说明这个字段可以为null## 2、在java中显示装配

@Resource
private Cat cat;
@Resource(name = “dog”)
private Dog dog;
private String name;


```

Resource和Autowired的区别:

都是用来自动装配的,都可以放在属性字段上

Autowired通过byType的方式实现,而且必须要求这个对象存在

Resource默认通过byname的方式实现,如果找不到名字,则通过byType实现,如果两个找不到就会报错

3、隐式自动装配【重要】

8、使用注解开发

在spring4.0之后,必须保证aop的包导入了

使用注解需要导入context约束,增加注解的支持

1、bean

@Component
public class User { public String name;public void setName(String name) {this.name = name;}
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns=""xmlns:xsi=""xmlns:context=""xsi:schemaLocation="://www.springframework.org/schema/beans/spring-beans.xsd://www.springframework.org/schema/context/spring-context.xsd"><context:component-scan base-package="com.kuangshen.pojo"/><context:annotation-config/></beans>

2、属性注解

@Component
public class User {//@Value("kuan")public String name;@Value("kuan")public void setName(String name) {this.name = name;}
}

3、衍生注解

@Component有几个衍生注解
我们在web开发中,会按照mvc三层架构分层
dao			   @Repository
service		@Service
controller	    @Controller
这四个注解功能都是一样的,都是代表将某个类注册到spring容器中,装配bean

4、自动配置注解

5、作用域

@Component
@Scope("singleton")//单例模式
public class User {//@Value("kuan")public String name;@Value("kuan")public void setName(String name) {this.name = name;}
}

6、小结

xml和注解:

xml是万能的,适用于任何场合

注解不是自己类使用不了,维护相对复杂

最佳实践:

xml用来管理bean

注解只负责属性的注入

我们在使用的过程中只需要注意一个问题,必须让注解生效,就需要开启注解的支持

9、完全使用java的配置spring

现在完全不使用spring的xml配置,全交给java来做

javaConfig是Spring的一个子项目,在spring4之后,他成为了一个新功能

配置文件

@Configuration//也会被spring容器中,因为他也死一个@Component.代表这是一个配置类,就和我们之前看的beans.xml一样
@ComponentScan("com.kuangshen.pojo")
@Import(config1.class)
public class config {//注册一个bean,就相当于我们之前写的bean标签//这个方法的名字,就相当于bean标签中的id属性//这个方法的返回值,就相当于bean标签中的class属性@Beanpublic User getUser(){return new User();}
}
@Configuration//也会被spring容器中,因为他也死一个@Component.代表这是一个配置类,就和我们之前看的beans.xml一样
public class config1 {//注册一个bean,就相当于我们之前写的bean标签//这个方法的名字,就相当于bean标签中的id属性//这个方法的返回值,就相当于bean标签中的class属性@Beanpublic User getUser(){return new User();}
}
//这个注解就是说明这个类被spring接管了
@Component
public class User {String name;public String getName() {return name;}@Value("pcy")public void setName(String name) {this.name = name;}
}
public class MyTest {public static void main(String[] args) {ApplicationContext context = new AnnotationConfigApplicationContext(config.class);User user = context.getBean("user",User.class);System.out.println(user.getName());}
}

这种纯java的配置方式,在SpringBoot随处可见!

10、代理模式

中介:帮助一些人做一些事情

为什么要学习代理模式?

因为这是springAOP的底层【SpringAOP和SpringMVC】

代理模式分类:

  • 静态代理
  • 动态代理

什么是代理模式?

10.1、静态代理

角色分析

  • 抽象角色:一般会使用接口或者抽象类来解决
  • 真实角色:被代理的角色
  • 代理角色:代理角色,代理真实角色后我们会做一些附属操作
  • 客户:访问代理对象的人

代理模式的好处:

  • 可以使真实角色的操作更加纯粹,不用关注一些公共的业务
  • 公共也就交给代理角色!实现了业务的分工
  • 公共业务发生扩展的时候,方便集中管理

缺点:

  • 一个真实角色就会产生一个代理角色,开发会变低
public interface Rent {public void rent();
}
public class Host implements Rent {public void rent() {System.out.println("房东要出租房子");}
}
package com.kuangshen.demo01;
public class Proxy implements Rent{Host host;public Proxy(Host host) {this.host = host;}public Proxy() {}public void rent() {host.rent();}//看房public void seeHouse() {System.out.println("看房");}
}
public class Client {public static void main(String[] args) {//房东要租房子Host host=new Host();//代理角色,中介一般会有一些附属操作Proxy proxy = new Proxy(host);//你不用面对房东,直接找中介proxy.rent();proxy.seeHouse();}
}

10.2、加深理解

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("查询了一个用户");}
}
public class UserServiceProxy implements UserService{private UserServiceImpl userService;public UserServiceImpl getUserService() {return userService;}public void setUserService(UserServiceImpl userService) {this.userService = userService;}public void add() {}public void delete() {}public void update() {}public void select() {}
}
public class Client {public static void main(String[] args) {UserServiceImpl userService=new UserServiceImpl();UserServiceProxy userServiceProxy=new UserServiceProxy();userServiceProxy.setUserService(userService);userServiceProxy.add();}
}

10.3、动态代理

动态代理和静态代理角色一样

动态代理的代理类是动态代理是动态生成的,不是我们直接写的

动态代理分为两大类:基于接口的动态代理,基于类的动态代理

  • 基于接口的------JDK动态代理
  • 基于类的:cglib
  • java字节码实现:javasist
package com.kuangshen.demo04;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class ProxyInvocationHander implements InvocationHandler {//被代理的接口private Object target;public void setTarget(Object target) {this.target = target;}//生成得到代理类public Object getProxy(){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);}
}
package com.kuangshen.demo04;import com.kuangshen.demo02.UserService;
import com.kuangshen.demo02.UserServiceImpl;/*** @author pcy* @date 2021/2/15 - 16:27*/
public class Client {public static void main(String[] args) {UserServiceImpl userService = new UserServiceImpl();//代理角色不存在ProxyInvocationHander hander = new ProxyInvocationHander();//设置要处理的对象hander.setTarget(userService);//动态生成代理类UserService proxy = (UserService) hander.getProxy();proxy.delete();}
}

动态代理的好处:

  • 可以使真实角色的操作更加纯粹,不用关注一些公共的业务
  • 公共也就交给代理角色,实现了业务的分工
  • 公共业务发生拓展的时候,方便集中管理
  • 一个动态代理类代理的是一个借口,一般就是对应的一类业务
  • 一个动态代理类可以代理多个类,只要实现了同一个接口就可以

12、整合Mybatis

1、导入相关jar包

<dependencies><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.13</version></dependency><dependency><groupId>mybatis</groupId><artifactId>mybatis</artifactId><version>3.4.5</version></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.47</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-webmvc</artifactId><version>5.3.3</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-jdbc</artifactId><version>5.2.7.RELEASE</version></dependency><dependency><groupId>org.aspectj</groupId><artifactId>aspectjweaver</artifactId><version>1.8.4</version></dependency><dependency><groupId></groupId><artifactId></artifactId></dependency><!-- .mybatis/mybatis-spring --><dependency><groupId>org.mybatis</groupId><artifactId>mybatis-spring</artifactId><version>2.0.6</version></dependency><!-- .springframework/spring-jdbc -->
<dependency><groupId>org.springframework</groupId><artifactId>spring-jdbc</artifactId><version>5.3.3</version>
</dependency>
<!-- .springframework/spring-jdbc -->
<dependency><groupId>org.springframework</groupId><artifactId>spring-jdbc</artifactId><version>5.3.3</version>
</dependency></dependencies>

编写数据源配置

sqlSessionFactory

sqlSessionTemplate

需要给接口加实现类

将自己写的实现类注入到spring中

测试使用

编写一个实体类

public class User {int id;String name;String pwd;@Overridepublic String toString() {return "User{" +"id=" + id +", name='" + name + '\'' +", pwd='" + pwd + '\'' +'}';}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getPwd() {return pwd;}public void setPwd(String pwd) {this.pwd = pwd;}public int getId() {return id;}public void setId(int id) {this.id = id;}public User() {}public User(int id, String name, String pwd) {this.id = id;this.name = name;this.pwd = pwd;}
}

编写接口UserMapper

public interface UserMapper {public List<User> selectUser();
}

编写配置映射文件UserMapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Config 3.0//EN"".dtd">
<mapper namespace="com.kuangshen.dao.UserMapper"><select id="selectUser" resultType="user">select * from user</select>
</mapper>

编写mybatis-config.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configurationPUBLIC "-//mybatis.org//DTD Config 3.0//EN"".dtd">
<configuration><typeAliases><package name="com.kuangshen.pojo"/></typeAliases>
</configuration>

编写spring-dao.xml连接数据源

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns=""xmlns:xsi=""xsi:schemaLocation="://www.springframework.org/schema/beans/spring-beans.xsd"><!--使用DataSource:使用Spring的数据源替换Mybatiss的配置c3p0 dbcp这里我们使用Spring提供的JDBC--><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/mall"/><property name="username" value="root"/><property name="password" value="123456"/></bean><!--sqlSessionFactory--><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/kuangshen/dao/*.xml"/></bean><!--SqlSessionTemplate:就是我们使用的sqlSession--><bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate"><!--因为没有set方法--><constructor-arg index="0" ref="sqlSessionFactory"/></bean><bean id="userMapper" class="com.kuangshen.dao.UserMapperImpl"><property name="sqlSession" ref="sqlSession"/></bean>
</beans>

编写UserMapperImpl实现类

方式一:UserMapperImpl.java

public class UserMapperImpl implements UserMapper {//我们所有的操作,读实用sqlSession来执行,现在都是使用SqlSessionTempleprivate SqlSessionTemplate sqlSession;public void setSqlSession(SqlSessionTemplate sqlSession){this.sqlSession=sqlSession;}public List<User> selectUser() {UserMapper mapper=sqlSession.getMapper(UserMapper.class);return mapper.selectUser();}
}

方式二UserMapperImpl2.java

public class UserMapperImpl2 extends SqlSessionDaoSupport implements UserMapper{public List<User> selectUser() {SqlSession sqlSession = getSqlSession();return getSqlSession().getMapper(UserMapper.class).selectUser();}
}

编写application.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns=""xmlns:xsi=""xsi:schemaLocation="://www.springframework.org/schema/beans/spring-beans.xsd"><import resource="classpath:spring-dao.xml"/><bean id="userMapper" class="com.kuangshen.dao.UserMapperImpl"><property name="sqlSession" ref="sqlSession"/></bean><bean id="userMapper2" class="com.kuangshen.dao.UserMapperImpl2"><property name="sqlSessionFactory" ref="sqlSessionFactory"/></bean>
</beans>

编写测试类

public class Test {@org.junit.Testpublic void test(){ApplicationContext context = new ClassPathXmlApplicationContext("application.xml");UserMapper userMapper = context.getBean("userMapper", UserMapper.class);for (User userMappers:userMapper.selectUser()){System.out.println(userMappers);}}
}

13、声明式事务

要么都成功,要么都失败

事务在项目中十分重要,涉及到数据的一致性问题

把一组业务当成一个业务来做

确保完整性和一致性

事务ACID原则:

  • 原子性:要么都成功,要么都失败

  • 一致性:保持一致性

  • 隔离性:多个业务可能操作同一个资源,防止数据损坏

  • 持久性:事务一旦完成了,无论系统发生什么问题,结果都不会被影响,被持久化的写到存储器中

1、spring中的事务管理

声明式事务:AOP

编程式事务:需要在代码中,进行事务管理

思考:为什么需要事务?

  • 如果不配置事务,可能需要数据提交不一致的情况下;
  • 如果我们不在spring中去配置声明式事务,我们就需要在代码中手动配置事务
  • 事务在项目的开发中十分重要,涉及到数据的一致性。

实体类

public class User {int id;String name;String pwd;@Overridepublic String toString() {return "User{" +"id=" + id +", name='" + name + '\'' +", pwd='" + pwd + '\'' +'}';}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getPwd() {return pwd;}public void setPwd(String pwd) {this.pwd = pwd;}public int getId() {return id;}public void setId(int id) {this.id = id;}public User() {}public User(int id, String name, String pwd) {this.id = id;this.name = name;this.pwd = pwd;}
}

接口

public interface UserMapper {public List<User> selectUser();//添加一个用户int addUser(User user);//删除一个用户int deleteUser(int id);
}

UserMapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Config 3.0//EN"".dtd">
<mapper namespace="com.kuangshen.dao.UserMapper"><select id="selectUser" resultType="user">select * from user</select><insert id="addUser" parameterType="user">insert into user(id,name,pwd) values(#{id},#{name},#{pwd})</insert><delete id="deleteUser" parameterType="int">delete from user where id=#{id}</delete>
</mapper>

UserMapperImpl2.java

public class UserMapperImpl2 extends SqlSessionDaoSupport implements UserMapper{public List<User> selectUser() {User user=new User(2,"u","12");SqlSession sqlSession = getSqlSession();UserMapper mapper = sqlSession.getMapper(UserMapper.class);mapper.addUser(user);mapper.deleteUser(1);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);}
}

mybatis-config.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configurationPUBLIC "-//mybatis.org//DTD Config 3.0//EN"".dtd">
<configuration><typeAliases><package name="com.kuangshen.pojo"/></typeAliases>
</configuration>

spring-dao.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns=""xmlns:xsi=""xmlns:aop=""xmlns:tx=""xsi:schemaLocation="://www.springframework.org/schema/beans/spring-beans.xsd://www.springframework.org/schema/aop/spring-aop.xsd://www.springframework.org/schema/aop/spring-tx.xsd"><!--使用DataSource:使用Spring的数据源替换Mybatiss的配置c3p0 dbcp这里我们使用Spring提供的JDBC--><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/mall"/><property name="username" value="root"/><property name="password" value="123456"/></bean><!--sqlSessionFactory--><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/kuangshen/dao/*.xml"/></bean><!--SqlSessionTemplate:就是我们使用的sqlSession--><bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate"><!--因为没有set方法--><constructor-arg index="0" ref="sqlSessionFactory"/></bean><!--配置声明式事务--><bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><!--<constructor-arg ref="dataSource" />--><property name="dataSource" ref="dataSource"/></bean><!--结合aop实现事务的织入--><!--配置事务通知--><tx:advice id="txAdvice" transaction-manager="transactionManager"><!--给那些方法配置事务--><!--p配置事务的传播特性:new  默认:REQUIREDread-only:只读--><tx:attributes><tx:method name="add" propagation="REQUIRED"/><tx:method name="update" propagation="REQUIRED"/><tx:method name="query" read-only="true"/><tx:method name="*" propagation="REQUIRED"/><tx:method name="delete" propagation="REQUIRED"/></tx:attributes></tx:advice><aop:config><aop:pointcut id="txPocut" expression="execution(* com.kuangshen.dao.*.*(..))"/><aop:advisor advice-ref="txAdvice" pointcut-ref="txPocut"/></aop:config>
</beans>

application.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns=""xmlns:xsi=""xsi:schemaLocation="://www.springframework.org/schema/beans/spring-beans.xsd"><import resource="classpath:spring-dao.xml"/><bean id="userMapper2" class="com.kuangshen.dao.UserMapperImpl2"><property name="sqlSessionFactory" ref="sqlSessionFactory"/></bean>
</beans>

测试:

public class Test {@org.junit.Testpublic void test(){ApplicationContext context = new ClassPathXmlApplicationContext("application.xml");UserMapper userMapper = context.getBean("userMapper2", UserMapper.class);for (User userMappers:userMapper.selectUser()){System.out.println(userMappers);}}
}

pom.xml依赖配置

<properties><spring.version>5.2.3.RELEASE</spring.version>
</properties>
<dependency><groupId>org.springframework</groupId><artifactId>spring-core</artifactId><version>${spring.version}</version>
</dependency>
<dependency><groupId>org.springframework</groupId><artifactId>spring-web</artifactId><version>${spring.version}</version>
</dependency>
<dependency><groupId>org.springframework</groupId><artifactId>spring-oxm</artifactId><version>${spring.version}</version>
</dependency>
<dependency><groupId>org.springframework</groupId><artifactId>spring-tx</artifactId><version>${spring.version}</version>
</dependency>
<dependency><groupId>org.springframework</groupId><artifactId>spring-jdbc</artifactId><version>${spring.version}</version>
</dependency>
<dependency><groupId>org.springframework</groupId><artifactId>spring-webmvc</artifactId><version>${spring.version}</version>
</dependency>
<dependency><groupId>org.springframework</groupId><artifactId>spring-aop</artifactId><version>${spring.version}</version>
</dependency>
<dependency><groupId>org.springframework</groupId><artifactId>spring-context-support</artifactId><version>${spring.version}</version>
</dependency>
<dependency><groupId>org.springframework</groupId><artifactId>spring-test</artifactId><version>${spring.version}</version>
</dependency>