Spring的小屋

Spring Framework

About Spring

  • About Spring --- 一项管理对象的技术

    • Rod Johnson --- Spring之父

    • 主线 --- IOC、AOP、声明式事务和整合Mybatis

    • Spring是分层的Java SE/EE应用full-stack轻量级开源框架,以IoC(Inverse Of Control 反转控制)和AOP(Aspect OrientedProgramming 面向切面编程)为内核

    • 提供了展现层(web层)SpringMVC(还有Struts、Struts2)和持久层(dao层)SpringJDBCTemplate(还有Mybatis、Hibernate)以及业务层事务管理等众多的企业级应用技术,还能整合开源世界众多著名的第三方框架和类库,逐渐成为使用最多的JavaEE企业应用开源框架

    • Spring的生态圈提供若干个项目,每个项目用于完成特定的功能

    • 官网:spring.io

    • 整合现有的轻量级框架,非入侵式
  • Spring全家桶(家族)

    • Spring Framework --- Spring生态圈中最基础的项目,是其它项目的根基
    • Spring Boot --- 简化开发基础上加速开发
    • Spring Cloud --- 分布式之微服务架构相关
    • Spring Data
    • Spring Security
  • Spring发展历程
    • 2004年,Spring1.0 --- 纯配置文件开发
    • 2006年,Spring2.0 --- 配置文件+注解开发
    • 2009年,Spring3.0 --- 纯注解开发
    • 2013年,Spring4.0
    • 2017年9月发布Spring5.0通用版(GA)
  • Spring的优势(简化开发+框架整合)
    • 方便解耦,简化开发
      • 通过Spring提供的IoC容器,可以将对象间的依赖关系交由Spring进行控制,避免硬编码所造成的的过度耦合,用户也不必再为单例模式类、属性文件解析等这些很底层的需求编写代码,可以更专注于上层的应用
    • AOP编程的支持
      • 通过Spring的AOP功能,方便进行切面编程,许多不容易用传统OOP实现的功能可以通过AOP轻松实现
    • 声明式事务的支持
      • 可以将我们从单调烦闷的事务管理代码中解脱出来,通过声明式方式灵活的进行事务管理,提高开发效率和质量
    • 方便程序的测试(集成jUnit)
      • 可以用非容器依赖的编程方式进行几乎所有的测试工作,测试不再是昂贵的操作,而是随手可做的事情
    • 方便集成各种优秀框架 
      • Spring对各种优秀框架(Struts、Hibernate、Hessian、Quartz)的支持
    • 降低JavaEE API的使用难度
      • Spring对JavaEE API(如JDBC、JavaMail、远程调用...)进行了薄薄的封装,降低了这些API的使用难度
    • Java源码经典学习典范
      • Spring的源代码设计精妙、结构清晰、匠心独具,处处体现大师对Java设计模式灵活运用以及对Java技术的高深造诣,它的源代码无疑是Java技术的最佳实践的典范
    • 简化开发:IoC、AOP(声明式事务处理属于Spring中AOP的具体应用)
    • 框架整合:Mybatis(整合Mybatis属于Spring中IOC的具体应用)、Mybatis-plus、Struts、Struts2、Hibernate...
  • Spring的体系结构
    • 核心层
      • Core Container:核心容器,其它模块都依赖此模块
    • AOP层
      • AOP:面向切面编程,依赖核心层容器,目的是在不改变原有代码的前提下对其进行功能增强
      • Aspects:AOP是思想,Aspects是对AOP思想的具体实现
    • 数据层
      • Data Access:数据访问,Spring全家桶中有对数据库访问的具体实现技术
      • Data Integration:数据集成,Spring支持整合其它的数据层解决方案(Mybatis)
      • Transactions:事务,Spring中事务管理是Spring AOP思想的一个具体实现
    • Web层
      • Web开发,在SpringMVC框架中学习
    • Test层
      • Spring整合了Junit来完成单元测试和集成测试
  • 核心概念
    • 代码书写现状 --- 耦合度偏高
      • 业务层需要调用数据层的方法,就需要在业务层new数据层的对象
      • 如果数据层的实现类发生变化,则业务层的代码也需要跟着改变,又要进行编译打包和重部署
    • 解决方案
      • 使用对象时将程序主动new产生对象,转换为由外部(SpringIOC容器)提供对象
      • 接口不能实例化对象
    • IoC(Inversion of Control):控制反转
      • 问题:业务层不想new对象,运行的时候又需要这个对象
      • 解决:对象的创建控制权由程序转移到外部,这种思想称为控制反转
      • Spring和IOC关系 --- Spring技术对IOC思想进行了实现
    • DI(Dependency Injection):依赖注入
      • 在容器中建立bean与bean之间的依赖关系的整个过程称为依赖注入
      • IOC容器中创建好service和dao对象后依然不能执行原因 --- service对象和dao对象没有关联
    • Bean:被创建或管理的对象在IoC容器中统称为Bean
    • IOC和DI两个概念的最终目标:充分解耦
      • 使用IoC容器管理bean(IoC)
      • 在IoC容器内将有依赖关系的bean进行关系绑定(DI)
      • 结果:使用对象直接从IOC容器中获取,且获取到的bean已经绑定依赖关系
    • Spring实现IOC和DI
      • 如何将被管理的对象告知IOC容器 --- applicationContext.xml配置文件
      • 获取IOC容器 --- Spring框架提供的接口
      • 容器获取bean --- 调用Spring框架提供的接口中的方法
      • 使用Spring的依赖 --- 用别人的东西,就需要在pom.xml添加对应依赖
      • 在配置文件中完成bean的配置
  • Spring相关API
    • ApplicationContext的继承关系
      • ApplicationContext --- 接口类型,代表应用上下文,可以通过其实例获得Spring容器中的bean
    • ApplicationContext的实现类
      • ClassPathXmlApplicationContext
        • 从类的根路径下加载配置文件,推荐
      • FileSystemXmlApplicationContext
        • 从磁盘路径上加载配置文件,配置文件可以在磁盘的任意位置
      • AnnotationConfigApplicationContext
        • 当使用注解配置容器对象时,需要使用此类来创建Spring容器,它用来读取注解
    • getBean()方法的使用
      • app.getBean("id") --- 根据bean的id从容器中获得bean,返回的是Object需要强转
      • app.getBean(Class) --- 根据类型从容器中匹配bean,当容器中相同类型的bean有多个时报错

Spring入门

  • IoC步骤
    • Spring相关依赖
      • <!--context依赖core、beans、expression-->
      • <dependency>
        • <groupId>org.springframework</groupId>
        • <artifactId>spring-context</artifactId>
        • <version>5.0.5.RELEASE</version>
      • </dependency> 
    • Dao层接口和实现类(创建Bean)
      • public interface UserDao{
      • public void save();
      • }
      • ---------------------------------------------------
      • public class UsreDaoImpl implements UserDao{
      • @Override
      • public void save(){
      • System.out.println("save running");
      • }
      • }
    • Spring核心配置文件applicationContext.xml
      • <?xml version="1.0" encoding="UTF-8" ?>
      • <beans xmlns="http://www.springframework.org/schema/beans" 
        • xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        • xsi:schemaLocation="
          • http://www.springframework.org/schema/beans
          • http://www.springframework.org/schema/beans/spring-beans.xsd>
      • </beans>
    • Spring核心配置文件中配置UserDaoImpl的bean
      • <bean id="userDao" class="com.smallstu.dao.impl.UserDaoImpl"/>
        • bean标签配置bean
        • id属性给bean起名字,id属性在同一个上下文中(配置文件)不能重复
        • class属性表示给bean定义类型
    • 获取bean --- 通过IoC容器
      • public class UserDaoTest{ 
      • public static void main(String[] args){
      • ---------------------------------------------------
      • ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
      • UserDao userDao = (UserDao) app.getBean("userDao"); 
      • ---------------------------------------------------
      • UserDao userDao = app.getBean("userDao",UserDao.class); --- 添加UserDao.class则不再需要强转
      • userDao.save();
      • }
      • }
  • DI步骤 --- 将Dao对象注入Service
    • 删除使用new的形式创建对象的代码,提供依赖对象对应的setter方法
      • public class BookServiceImpl implements BoolService{
      • private BookDao bookDao;
      • public void save(){
      • bookDao.save();
      • }
      • -----------------------------------------------------------------------------------------------------------------------
      • public void setBookDao(BookDao bookDao){ 
      • this.bookDao = bookDao;
      • }
      • }
    • 配置文件中添加依赖注入配置
      • <?xml version="1.0" encoding="UTF-8" ?>
      • <beans xmlns="http://www.springframework.org/schema/beans" 
        • xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        • xsi:schemaLocation="
          • http://www.springframework.org/schema/beans
          • http://www.springframework.org/schema/beans/spring-beans.xsd>
        • <bean id="bookDao" class="com.smallstu.dao.impl.BookDaoImpl"/>
        • ----------------------------------------------
        • <bean id="bookService" class="com.smallstu.service.impl.BookServiceImpl"/>
          • <property name="booDao" ref="bookDao"/> --- 将dao注入service
        • </bean>
      • </beans>
    • 依赖注入说明
      • property标签表示配置当前bean的属性
      • name属性表示配置哪一个具体的属性
        • name="bookDao":对应构造函数中方法形参的参数名
      • ref属性表示参照哪一个bean(在容器中不存在则报错)
        • ref="bookDao":指向Spring的IoC容器中其它bean对象
      • ref的属性值可以是另一个bean的name属性值,但建议使用id进行注入
  • Spring配置
    • bean标签基本配置
      • 功能:定义Spring核心容器管理的对象
      • 默认情况下它调用的是类中的无参构造器,如果没有无参构造函数则不能创建成功
      • 基本属性
        • id:bean实例在Spring容器中的唯一标识
        • class:bean的全路径类名
    • bean别名配置
      • 使用 --- name
        • 可以定义多个,使用逗号、分号或空格分隔
        • Ebi(Enterprise Business Interface):企业业务接口
      • 实例
        • <bean id="bookDao" name="dao bookDaoImpl" class="com.smallstu.dao.impl.BookDaoImpl"/>
        • <bean name="service,bookServiceImpl" class="com.smallstu.service.impl.BookServiceImpl"/>
          • ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
          • //根据bean标签的name属性获取bean对象
          • BookService bookService = (BookService) ctx.getBean("service4");
          • bookService.save();
        • 无论通过id还是name获取bean,无法找到将抛出异常:NoSuchBeanDefinaitionException
    • bean标签范围配置
      • scope:为bean设置作用范围(可选值为单例singloton、非单例prototype)
        • singleton:默认值,单例的
          • @Test
          • public void test(){
          • ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
          • UserDao userDao1 = (UserDao) app.getBean("userDao");
          • UserDao userDao2 = (UserDao) app.getBean("userDao");
          • System.out.println(userDao1);
          • System.out.println(userDao2); --- 两个对象地址相同
          • }
        • prototype:多例的
          • <bean id="userDao" class="com.smallstu.dao.impl.UserDaoImpl" scope="prototype"/>
          • ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
          • UserDao userDao1 = (UserDao) app.getBean("userDao");
          • UserDao userDao2 = (UserDao) app.getBean("userDao");
          • System.out.println(userDao1);
          • System.out.println(userDao2); --- 两个对象地址不同
        • request:web项目中,Spring创建一个Bean的对象,将对象存入request域中
        • session:web项目中,Spring创建一个Bean的对象,将对象存入session域中
        • global session:web项目中,应用在Portlet环境,如果没有Portlet环境,那么globalSession相当于session 
        • 验证IOC容器中对象是否为单例
          • 思路:同一个bean获取两次,将对象打印到控制台,看打印出的地址值是否一致
          • 结论:默认情况下,Spring创建的bean对象都是单例的
        • 创建非单例的bean对象如何实现
          • 修改bean的scope属性为prototype
          •  <bean id="bookDao" name="dao" class="com.itheima.dao.impl.BookDaoImpl" scope="prototype"/>
        • 思考
          • 为什么bean默认为单例
            • 避免对象的频繁创建与销毁,达到了bean对象的复用
          • bean在容器中是单例的,会不会产生线程安全问题
            • 如果对象是有状态对象,即该对象有成员变量可以用来存储数据的
            • 因为所有请求线程共用一个bean对象,所以会存在线程安全问题
            • 如果对象是无状态对象,即该对象没有成员变量没有进行数据存储的
            • 因方法中的局部变量在方法调用完成后会被销毁,所以不会存在线程安全问题
          • 哪些bean对象适合交给容器进行管理
            • 表现层对象、业务层对象、数据层对象、工具对象
          • 哪些bean对象不适合交给容器进行管理
            • 封装实例的域对象,因为会引发线程安全问题,所以不适合
      • 当scope的取值为singleton时
        • Bean的实例化个数:1个
        • Bean的实例化时机:Spring核心文件被加载时,实例化配置的Bean实例
        • Bean的生命周期
          • 对象创建:当应用加载,创建容器时,对象就被创建了
          • 对象运行:只要容器在,对象一直活着
          • 对象销毁:当应用卸载,销毁容器时,对象就被销毁了
      • 当scope的取值为prototype时
        • Bean的实例化个数:多个
        • Bean的实例化时机:当调用getBean()方法时实例化Bean
        • Bean的生命周期
          • 对象创建:当使用对象时,创建新的对象实例
          • 对象运行:只要对象在使用中,就一直活着
          • 对象销毁:当对象长时间不用时,被Java的垃圾回收器回收
    • Bean的生命周期配置 --- 从创建到消亡的过程
      • init-method:指定类中初始化方法名称
      • destory-method:指定类中销毁方法名称
        • <bean id="userDao" class="com.smallstu.dao.impl.UserDaoImpl" init-method="init" destory-method="destory"/>
        • public class UserDaoImpl implements UserDao{
        • public UserDaoImpl(){}
        • public void init(){}
        • public void destory(){}
        • }
      • 环境准备
        • BookDao、BookDaoImpl、BookService和BookServiceImpl类
        • Spring核心配置文件
        • 测试类 --- 加载IoC容器从中获取对应的bean对象
          • ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
          • BookDao bookDao = (BookDao) app.getBean("bookDao");
          • bookDao.save();
      • 生命周期设置
        • 为BookDao添加生命周期的控制方法,具体控制有两个阶段
          • bean创建之后想要添加内容,如用来初始化需要用到的资源
          • bean销毁之前想要添加内容,如用来释放用到的资源
        • 添加初始化和销毁方法
          • public class BookDaoImpl implements BookDao{
          • public void save(){System.out.println("book dao save");}
          • public void init(){System.out.println("init");}
          • public void destory(){System.out.println("destory");}
          • }
        • 配置生命周期
          • <bean id="bookDao" class="com.smallstu.dao.impl.BookDaoImpl" init-method="init" destroy-method="destory"/>
        • 测试程序
          • init和save方法被执行,destory方法没有被执行
            • Spring的IoC容器运行在JVM容器中
            • 执行main方法后JVM启动,Spring加载核心配置文件生成IoC容器,从容器中获取bean对象然后调方法执行
            • main方法执行完后JVM退出,此时IoC容器中的bean还没来得及销毁就已经结束,所以没有调用destory方法
        • 解决 --- close关闭容器
          • ApplicationContext中没有close方法
          • 需要将ApplicationContext更换成ClassPathXmlApplicationContext
            • ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
          • 调用ctx的close方法
            • ctx.close();
          • 由此destory就可被执行
        • 注册钩子关闭容器
          • 在容器未关闭之前提前设置好回调函数,让JVM在退出之前调用此回调函数来关闭容器
          • 调用ctx的registerShutdownHook()方法 --- 在ApplicationContext中也没有
            • ctx.registerShutdownHook();
        • close()和registerShutdownHook()比较
          • 相同点:都能用来关闭容器
          • 不同点:close在调用的时候关闭,registerShutdownHook在JVM退出前调用关闭
      • Spring提供两个接口实现生命周期的控制 --- 不用再进行配置init-method、destory-method
        • 修改BookDaoImpl类,再添加两个接口InitializingBean、DisposableBean
          • public class BookServiceImpl implements BookService,InitializingBean,DisposableBean{
          • private BookDao bookDao;
          • public void setBookDao(BookDao bookDao){this.bookDao = bookDao;}
          • public void save(){System.out.println("book service save"); bookDao.save();}
          • public void destory(){System.out.println("service destory");}
          • public void afterPropertiesSet(){System.out.println(service init);}
          • }
        • 测试即可
      • 细节
        • 对于InitializingBean接口中的afterPropertiesSet方法,翻译为属性设置之后
        • 对于BookServiceImpl来说,bookDao是它的一个属性
        • setBookDao方法是Spring的IoC容器为其注入属性的方法
        • 思考:afterPropertiesSet和setBookDao哪个先执行
          • setBookDao先执行
          • 所以初始化方法会在类中属性设置之后执行
    • Bean实例化三种方式
      • 无参构造实例化
        • 说明
          • 默认根据无参构造方法创建对象
          • 如果Bean中没有默认无参构造,报BeanCreationException异常
      • 静态工厂实例化
        • public class StaticFactory{
        • public static UserDao createUserDao(){return new UserDaoImpl();}
        • }
        • --------------------------------------------------------------------------
        • <bean id="userDao" class="com.smallstu.factory.StaticFactory" factory-method="createUserDao"/>
        • --------------------------------------------------------------------------
        • UserDao userDao = StaticFactory.createUserDao();
        • userDao.save();
        • --------------------------------------------------------------------------
        • ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
        • UserDao userDao = app.getBean("userDao");
        • userDao.save();
      • 静态工厂的意义
        • 除new对象外还可以做其它一些业务操作
        • public class StaticFactory{
        • public static createUserDao(){
        • System.out.println("factory setup");
        • return new UserDaoImpl();
        • }
        • }
      • 工厂实例方法实例化
        • public class DynamticFactory{
        • public UserDao createUserDao(){return new UserDaoImpl();}
        • }
        • ------------------------------------------------------------------------
        • <bean id="factoryBean" class="com.smallstu.factory.DynamticFactory"/>
        • <bean id="userDao" factory-bean="factoryBean" factory-method="createUserDao"/>
        • ------------------------------------------------------------------------
        • DynamticFactory factory = new DynamticFactory();
        • UserDao userDao = factory.createUserDao();
        • userDao.save();
        • ------------------------------------------------------------------------
        • ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
        • UserDao userDao = (UserDao) app.getBean("userDao");
        • userDao.save();
      • 实例化工厂运行顺序
        • 创建实例化工厂对象,对应第一行配置
        • 调用对象中的方法来创建bean,对应第二行配置
          • bean-factory --- 工厂的实例对象
          • factory-method --- 工厂对象中的具体创建对象的方法名
      • FactoryBean的使用
        • 创建一个UserDaoFactory的类实现FactoryBean接口,并重写接口的方法
          • public class UserDaoFactoryBean implements FactoryBean<UserDao>{
          • public UserDao getObject(){return new UserDaoImpl();} --- 代替原始实例工厂中创建对象的方法
          • public Class<?> getObjectType(){return UserDao.class;} --- 返回所创建类的Class对象
          • }
        • 在Spring配置文件中配置
          • <bean id="userDao" class="com.smallstu.factory.UserDaoFactoryBean"/>
        • FactoryBean接口的三个方法
          • T getObject() throws Exception; --- 被重写后,在方法中进行对象的创建并返回
          • Class<?> getObjectType(); --- 被重写后,主要返回的是被创建类的Class对象
          • default boolean isSIngleton(){return true;} --- 作用是设置对象是否为单例(默认单例)
  • 依赖注入
    • 关于依赖注入
      • 依赖注入概念
        • 依赖注入(Dependency Injection):Spring框架核心IOC的具体实现
        • 编写程序时,通过控制反转把对象创建权交给Spring,但是代码中不可能出现没有依赖的情况,IOC解耦只是降低依赖关系,但不会消除(如:业务层仍会调用持久层的方法)
        • 类似业务层和持久层的依赖关系,在使用Spring之后,就由Spring来维护,简单说,就是坐等框架把持久层对象传入业务层,而不用手动去获取
      • Bean的依赖注入分析
        • 目前UserService实例和UserDao实例都存在于Spring容器中
        • 当前的做法是在容器外部获得UserService实例和UserDao实例,然后在程序中进行结合
        • 相当于是在Spring容器外部将Dao组装到Service内部完成操作
        • 因为UserService和UserDao都在Spring容器中,而最终程序直接使用的是UserService
        • 所以可以在Spring容器中,将UserDao设置到UserService中(如何设置) --- 将UserDao注入到UserService中
    • 依赖注入方式
      • 构造方法
        • 创建有参构造
          • public class UserServiceImpl implements UserService{
          • private UserDao userDao;
          • public UserServiceImple(UserDao userDao){this.userDao = userDao;}
          • public UserServiceImpl(){};
          • @Override
          • public void save(){userDao.save()}
          • }
        • 配置Spring容器调用有参构造进行注入
          • <bean id="userDao" class="com.smallstu.dao.impl.UserDaoImpl"/>
          • <bean id="userService" class="com.smallstu.service.imple.UserServiceImpl">
          • <constructor-arg name="userDao" ref="userDao"/>
          • </bean>
      • set方法
        • 在UserServiceImpl(bean)中定义引用类型属性,并提供可访问的set方法
          • public class UserServiceImpl implements UserService{
          • private UserDao userDao;
          • private BookDao bookDao;
          • public void setUserDao(UserDao userDao){
          • this.userDao = userDao;
          • }
          • public void setBookDao(BookDao bookDao){
          • this.booDao = bookDao;
          • }
          • ----------------------------------------------
          • @Override
          • public void save(){
          • userDao.save();
          • bookDao.save();
          • }
          • }
        • 配置中使用property标签的ref属性注入引用类型对象
          • <bean id="userDao" class="com.smallstu.dao.impl.UserDaoImpl"/>
          • <bean id="bookDao" class="com.smallstu.dao.impl.BookDaoImpl"/>
          • ----------------------------------------------------
          • <bean id="userService" class="com.smallstu.service.impl.UserServiceImpl">
          • <property name="userDao" ref="userDao"/>
          • <property name="bookDao" ref="bookDao"/>
          • </bean>
      • set方法-P命名空间
        • P命名空间本质也是set方法注入,只是更加方便,主要体现在配置文件中
          • 首先需要引入P命名空间
            • xmlns:p="http://www.springframework.org/schema/p"
          • 其次需要修改注入方式
            • <bean id="userService" class="com.smallstu.service.impl.UserServiceImpl" p:userDao-ref="userDao"/>
    • 依赖注入的数据类型
      • 普通数据类型注入
        • 在UserDaoImpl类中声明对应的简单数据类型的属性,并提供对应setter方法
          • public class UserDaoImpl implemetns UserDao{
          • private String company;
          • private int age;
          • --------------------------------------------------- 
          • public void setCompany(String company){this.company = company;}
          • public void setAge(int age){this.age = age;}
          • ---------------------------------------------------
          • public void save(){
          • System.out.println(company+"====="+age);
          • System.out.println("UserDao save method running");
          • }
          • }
        • 在applicationContext.xml核心配置文件中配置
          • <bean id="userDao" class="com.smallstu.dao.impl.UserDaoImpl">
            • <property name="company" value="alibaba"/>
            • <property name="age" value="18"/>
          • <bean/> --- 给bookDao注入简单类型数据(类型务必相匹配)
          • -----------------------------------------------------
          • <bean id="bookDao" class="com.smallstu.dao.ipml.BookDaoImpl"/>
          • <bean id="bookService" class="com.smallstu.service.impl.bookServiceImpl">
            • <property name="bookDao" ref="bookDao"/>
            • <property name="userDao" ref="userDao"/>
          • </bean> --- 给bookService注入bookDao和userDao
        • 说明
          • ref指向Spring的IoC容器中的另一个bean对象,对于简单数据类型,没有对应的bean对象
      • 集合数据类型注入List<String>
        • 在UserServiceImpl类中声明对应的集合类型的属性,并提供对应setter方法
          • public class UserServiceImpl implements UserService{
          • private List<String> strList;
          • ----------------------------------------------
          • public void setStrList(List<String> strList){this.strList = strList;}
          • ----------------------------------------------
          • public void save(){
          • System.out.println(strList);
          • System.out.println("UserService save method");
          • }
        • 在applicationContext.xml核心配置文件中配置
          • <bean id="userDao" class="com.smallstu.dao.impl.UserDaoImpl">
            • <property name="strList">
              • <value>aaa</value>
              • <value>bbb</value>
              • <value>ccc</value>
            • </property>
          • </bean>
      • 集合数据类型注入List<User>
        • 在UserDaoImpl类中声明对应的集合类型的属性,并提供对应setter方法
          • public class UserDaoImpl implements UserDao{
          • private List<User> userList;
          • ----------------------------------------------
          • public void setUserList(List<User> userList){this.userList = userList;}
          • ----------------------------------------------
          • public void save(){
          • System.out.println(userList);
          • System.out.println("UserDao save method");
          • }
        • 在applicationContext.xml核心配置文件中配置
          • <bean id="u1" class="com.smallstu.domain.User"/>
          • <bean id="u2" class="com.smallstu.domain.User"/>
          • <ban id="userDao" class="com.smallstu.dao.impl.UserDaoImpl"/>
            • <property name="userList">
              • <list>
                • <bean class="com.smallstu.domain.User"/>
                • <bean class="com.smallstu.domain.User"/>
                • <ref bean="u1"/>
                • <ref bean="u2"/>
              • </list>
            • </property>
          • </bean>
      • 集合数据类型注入Map<String,User>
        • 在UserDaoImpl类中声明对应的集合类型的属性,并提供对应setter方法
          • public class UserDaoImpl implements UserDao{
          • private Map<String,User> userMap;
          • ----------------------------------------------
          • public void setUserMap(Map<String,User> userMap){this.userMap = userMap;}
          • ----------------------------------------------
          • public void save(){
          • System.out.println(userMap);
          • System.out.println("UserDao save method");
          • }
        • 在applicationContext.xml核心配置文件中配置
          • <bean id="u1" class="com.smallstu.domain.User"/>
          • <bean id="u2" class="com.smallstu.domain.User"/>
          • <ban id="userDao" class="com.smallstu.dao.impl.UserDaoImpl"/>
            • <property name="userMap">
              • <map>
                • <entry key="user1" value-ref="u1"/>
                • <entry key="user2" value-ref="u2"/>
              • </map>
            • </property>
          • </bean>
      • properties
        • 在UserDaoImpl类中声明对应的Properties属性,并提供对应setter方法
          • public class UserDaoImpl implements UserDao{
          • private Properties properties;
          • ----------------------------------------------
          • public void setProperties(Properties properties){this.properties = properties;}
          • ----------------------------------------------
          • public void save(){
          • System.out.println(properties);
          • System.out.println("UserDao save method");
          • }
        • 在applicationContext.xml核心配置文件中配置
          • <ban id="userDao" class="com.smallstu.dao.impl.UserDaoImpl"/>
            • <property name="properties">
              • <props>
                • <prop key="p1">aaa</prop>
                • <prop key="p2">bbb</prop>
                • <prop key="p3">ccc</prop>
              • </props>
            • </property>
          • </bean>
    • 自动装配
      • IoC容器根据bean所依赖的资源在容器中自动查找并注入到bean中的过程 
      • 自动装配的方式
        • 按类型
        • 按名称
        • 按构造方法
        • 不启用自动装配
      • 完全自动装配的配置 --- 修改applicationContext.xml
        • 删除<property>标签
        • 在<bean>标签中添加autowire属性
      • 按照类型注入的配置
        • <bean class="com.smallstu.dao.impl.BookDaoImpl"/>
        • <bean id="bookService" class="com.smallstu.service.impl.BookServiceImpl" autowire="byType"/>
      • 说明
        • 需要注入的类中对应属性的setter方法不能省略
        • 被注入的对象必须要被Spring的IoC容器管理
        • 按照类型在Spring的IoC容器中如果找到多个对象,报NoUniqueBeanDefinitionException
      • 一个类型在IoC中有多个对象,此时就需要按照名称注入
        • <bean class="com.smallstu.dao.impl.BookDaoImpl"/>
        • <bean id="bookService" class="com.smallstu.service.BookServiceImpl" autowire="byName"/>
      • 说明
        • 按类型装配时,必须保障容器中相同类型的bean唯一
        • 按名称装配时,必须保障容器中具有指定名称的bean
        • 自动装配优先级低于setter注入和构造器注入,同时出现时自动装配配置失效
    • 引入其它配置文件(分模块开发)
      • 实际开发中Spring的配置非常多,导致Spring配置繁杂且体积大
      • 可以将配置进行拆解(分模块拆解),在Spring主配置文件中通过import标签进行加载
        • <import resource="applicationContext-xxx.xml">
        • applicationContext-user.xml
        • applicationContext-product.xml
    • 小结
      • <bean>
        • id属性
        • class属性
        • scope属性
        • <property> --- 属性注入
          • name属性
          • value属性
          • ref属性
          • <list>
          • <map>
          • <properties>
        • <constructor-arg>
      • <import>
  • Spring配置数据源(三方bean)
    • 手动创建c3p0数据源
      • 添加依赖
        • <dependency>
          • <groupId>c3p0</groupId>
          • <artifactId>c3p0</artifactId>
          • <version>0.9.1.1</version>
        • </dependency>
      • 测试
        • ComboPooledDataSource dataSource = new ComboPooledDataSource();
        • ---------------------------------------------------------------------------
        • dataSource.setDriverClass("com.mysql.jdbc.Driver");
        • dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/test");
        • dataSource.setUser("root");
        • dataSource.setPassword("000000");
        • ---------------------------------------------------------------------------
        • Connection connection = dataSource.getConnection();
        • System.out.println(connection);
        • connection.close();
    • 手动创建c3p0数据源 --- 加载配置文件
      • 添加依赖
        • <dependency>
          • <groupId>c3p0</groupId>
          • <artifactId>c3p0</artifactId>
          • <version>0.9.1.1</version>
        • </dependency>
      • 抽取jdbc.properties配置文件
        • jdbc.driverClassName=com.mysql.jdbc.Driver
        • jdbc.url=jdbc:mysql://location:3306/test
        • jdbc.username=root
        • jdbc.password=000000
      • 测试
        • ResourceBundle rb = ResourceBundle.getBundle("jdbc"); --- 读取配置文件
        • String driver = rb.getString("jdbc.driverClassName");
        • String url = rb.getString(jdbc.url);
        • String username = rb.getString(jdbc.username);
        • String password = rb.getString("jdbc.password");
        • -------------------------------------------------------
        • ComboPooledDataSource dataSource = new ComboPooledDataSource();
        • dataSource.setDriverClass("drier");
        • dataSource.setJdbcUrl("url");
        • dataSource.setUser("username");
        • dataSource.setPassword("password");
        • Connection connection = dataSource.getConnection();
        • System.out.println(connection);
        • connection.close();
    • IoC容器管理c3p0数据源
      • 导入依赖
        • <dependency>
          • <groupId>c3p0</groupId>
          • <artifactId>c3p0</artifactId>
          • <version>0.9.1.1</version>
        • </dependency>
      • 配置bean --- 让IoC管理DataSource对象
        • <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
          • <property name="driverClass" value="com.mysql.jdbc.Driver"/>
          • <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/smallstu"/>
          • <property name="user" value="root"/>
          • <property name="password" value="000000"/>
        • </bean>
      • 测试
        • ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
        • DataSource dataSource = (DataSource) app.getBean("dataSource");
        • Connection connection = dataSource.getConnection();
        • System.out.println(connection);
    • IoC容器管理c3p0数据源 --- 加载配置文件(第三方bean属性优化)
      • 导入依赖
        • <dependency>
          • <groupId>c3p0</groupId>
          • <artifactId>c3p0</artifactId>
          • <version>0.9.1.1</version>
        • </dependency>
      • 抽取jdbc.properties配置文件
        • jdbc.driverClassName=com.mysql.jdbc.Driver
        • jdbc.url=jdbc:mysql://location:3306/test
        • jdbc.username=root
        • jdbc.password=000000
      • 配置bean
        • 引入context命名空间和约束路径
          • 命名空间
            • xmlns:context="http://www/springframework.org/schema/context" --- applicationContext.xml加载jdbc.properties文件获取连接信息
          • 约束路径
            • http://www.springframework.org/schema/context
            • http://www.springframework.org/schema/context/spring-context.xsd
        • 实现
          • <context:property-placeholder location="classpath:jdbc.properties"/>
          • <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
            • <property name="driverClass" value="${jdbc.driverClassName}"/>
            • <property name="url" value="${jdbc.url}"/>
            • <property name="username" value="${jdbc.username}"/>
            • <property name="password" value="${jdbc.password}"/>
          • </bean>
      • 测试
        • ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
        • DataSource dataSource = (DataSource) app.getBean("dataSource");
        • Connection connection = dataSource.getConnection();
        • System.out.println(connection);
    • 手动创建druid数据源
      • 添加依赖
        • <dependency>
          • <groupId>aom.alibaba</groupId>
          • <artifactId>druid</artifactId>
          • <version>1.1.10</version>
        • </dependency>
      • 测试
        • DruidDataSource dataSource = new DruidDataSource();
        • ---------------------------------------------------------------------
        • dataSource.setDriverClass("com.mysql.jdbc.Driver");
        • dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/test");
        • dataSource.setUser("root");
        • dataSource.setPassword("000000");
        • ---------------------------------------------------------------------
        • DruidPooledConnection connection = dataSource.getConnection();
        • System.out.println(connection);
        • connection.close();
    • 手动创建Druid数据源 --- 加载配置文件
      • 添加依赖
        • <dependency>
        • <groupId>c3p0</groupId>
        • <artifactId>c3p0</artifactId>
        • <version>0.9.1.1</version>
        • </dependency>
      • 抽取jdbc.properties配置文件
        • jdbc.driverClassName=com.mysql.jdbc.Driver
        • jdbc.url=jdbc:mysql://location:3306/test
        • jdbc.username=root
        • jdbc.password=000000
      • 测试
        • ResourceBundle rb = ResourceBundle.getBundle("jdbc"); --- 读取配置文件
        • String driver = rb.getString("jdbc.driverClassName");
        • String url = rb.getString(jdbc.url);
        • String username = rb.getString(jdbc.username);
        • String password = rb.getString("jdbc.password");
        • -------------------------------------------------------
        • ComboPooledDataSource dataSource = new ComboPooledDataSource();
        • -------------------------------------------------------
        • dataSource.setDriverClass("drier");
        • dataSource.setJdbcUrl("url");
        • dataSource.setUser("username");
        • dataSource.setPassword("password");
        • -------------------------------------------------------
        • Connection connection = dataSource.getConnection();
        • System.out.println(connection);
        • connection.close();
    • IoC容器管理Druid数据源
      • 将DataSource的创建权交由Spring容器完成
        • DataSource有无参构造方法,而Spring默认就是通过无参构造方法实例化对象的
        • DataSource要想使用需要通过set方法设置数据库连接信息,而Spring可以通过set方法进行字符串注入
      • 添加依赖
        • <dependency>
        • <groupId>aom.alibaba</groupId>
        • <artifactId>druid</artifactId>
        • <version>1.1.10</version> 
        • </dependency>
      • 配置bean --- 让IoC管理DataSource对象
        • <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
          • <property name="driverClass" value="com.mysql.jdbc.Driver"/>
          • <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/smallstu"/>
          • <property name="user" value="root"/>
          • <property name="password" value="000000"/>
        • </bean>
      • 测试
        • ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
        • DataSource dataSource = (DataSource) app.getBean("dataSource");
        • Connection connection = dataSource.getConnection();
        • System.out.println(connection);
    • IoC容器管理Druid数据源 --- 加载配置文件
      • 导入依赖
        • <dependency>
          • <groupId>c3p0</groupId>
          • <artifactId>c3p0</artifactId>
          • <version>0.9.1.1</version>
        • </dependency>
      • 抽取jdbc.properties配置文件
        • jdbc.driverClassName=com.mysql.jdbc.Driver
        • jdbc.url=jdbc:mysql://location:3306/test
        • jdbc.username=root
        • jdbc.password=000000 
      • 配置bean
        • 引入context命名空间和约束路径
          • 命名空间
            • xmlns:context="http://www/springframework.org/schema/context" --- applicationContext.xml加载jdbc.properties文件获取连接信息
          • 约束路径
            • http://www.springframework.org/schema/context
            • http://www.springframework.org/schema/context/spring-context.xsd
        • 实现
          • <context:property-placeholder location="classpath:jdbc.properties"/>
          • <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
            • <property name="driverClass" value="${jdbc.driverClassName}"/>
            • <property name="url" value="${jdbc.url}"/>
            • <property name="username" value="${jdbc.username}"/>
            • <property name="password" value="${jdbc.password}"/>
          • </bean>
    • 小结
      • Spring容器加载properties配置文件
        • <context:property-placeholder location="xx.properties"/>
        • <property name="" value="${key}"/>
      • 说明
        • ComboPooledDataSource的属性通过setter方式进行注入
        • 想注入属性就需要在ComboPooledDataSource类或其上层类中有提供属性对应的setter方法
        • c3p0四个属性和Druid四个属性不一样
    • 获取单个属性
      • 需求:从properties配置文件中读取key为name的值,将其注入到BookDao中并在save方法中进行打印
      • 创建BookDao和BookDaoImpl类,为BookDaoImpl类添加name属性并提供setter方法
        • public interface BookDao{
        • public void save();
        • }
        • ------------------------------------------------------------------------------
        • public class BookDaoImpl implements BookDao{
        • private String name;
        • public void setName(String name){this.name = name;}
        • public void save(){System.out.println("book dao save" + name);}
        • }
      • 在applicationContext.xml中添加配置
        • 引入命名空间和约束路径
        • <context:property-placeholder location="jdbc.properties">
        • <bean>
          • <property name="name" value="${name}"/>
        • </bean>
    • properties配置文件中将key设置为username引发的问题
      • 获得的username对应的值是电脑用户名
      • 原因:<context:property-plcaeholder/>标签会加载系统的环境变量,而且环境变量的值会被优先加载
      • 查看系统的环境变量
        • public static void main(String[] args){
        • Map<String,String> env = System.getenv();
        • System.out.println(env);
        • }
        • 打印结果:USERNAME=XXX[本机用户名]
      • 解决
        • <context:property-placeholder location="jdbc.properties" system-properties-mode="NEVER"/>
        • system-properties-mode设置为NEVER表示不加载系统属性
        • 另一解决方案:避免使用username作为属性的key
    • 加载多个配置文件
      • 方式
        • <context:property-placeholder location="jdbc.properties,jdbc2.properties" system-properties-mode="NEVER"/>
        • <context:property-placeholder location="*.properties" system-properties-mode="NEVER"/>
        • <context:property-placeholder location="classpath:*.properties" system-properties-mode="NEVER"/>
        • <context:property-placeholder location="classpath*:*.properties" system-properties-mode="NEVER"/>
      • 说明
        • 方式三:从当前项目根路径下开始查找,推荐
        • 方式四:从当前项目或其所依赖的所有项目的根路径下查找

Spring注解开发

  • 注解开发定义bean:使用2.5版本提供的注解
    • 环境准备
      • 创建Maven项目
      • 添加Spring依赖
      • 创建applicationContext.xml配置文件
        • <bean id="bookDao" class="com.smallstu.dao.impl.BookDaoImpl"/>
      • 创建BookDao、BookDaoImpl、BookService、BookServiceImpl类
        • public interface BookDao{
        • public void save();
        • }
        • public class BookDaoImpl implements BookDao{
        • public void save(){System.out.println("book dao save");}
        • }
        • ----------------------------------------------------------------------
        • public interface BookService{
        • public void save();
        • }
        • public class BookServiceImpl implements BookService{
        • public void save(){System.out.println("book service save");}
        • }
    • 注解开发定义bean
      • 删除配置文件中的bean标签
      • BookDaoImpl类上添加@Component注解
        • @Component("bookDao")
        • public class BookDaoImpl implements BookDao{
        • public void save(){System.out.println("book dao save");};
        • }
        • @Component注解不能添加在接口上,接口不能创建对象
      • xml与注解对应关系
        • 一个注解就相当于一个Bean
        • 注解里的内容即为bean的id
        • 注解写在哪个类上,class就指该类的全类名
      • 配置Spring的注解包扫描
        • <context:component-scan base-package="com.smallstu"/>
      • 说明
        • component-scan
          • component:组件,Spring将管理的bean视作自己的一个组件
          • scan:扫描
        • base-package:指定Spring容器扫描的包路径,会扫描指定包及其子包中所有类上的注解
          • 包路径越多扫描的范围越小速度越快
          • 包路径越少扫描的范围越大速度越慢
          • 一般扫描到项目的组织名称,即Maven下的groupId
        • BookDaoImpl类没有起别名,所以在在容器中是根据类型获取对象
        • @Component注解如果不起别名,会有一个默认值就是当前类名首字母小写,所以也可以按照名称获取
      • @Component注解衍生出@Controller、@Service、@Reposotory三个注解
        • 类型:类注解
        • 位置:类上方
        • 作用:设置该类为Spring容器管理的bean
        • 属性:value(默认):定义bean的id
        • 说明:四个注解作用相同,只是为了区分被标注的类属于哪一层结构(表现层,业务层,数据层)
  • 纯注解开发 --- 使用3.0版本提供的注解(使用Java类替代配置文件)
    • 实现步骤
      • 创建配置类 --- SpirngConfig.java
        • public class SpringConfig{
        • }
      • 标识该类为配置类 --- 添加@Configuration注解替换applicationContext.xml
        • @Configuration
        • public class SprignConfig{
        • }
      • 使用注解替换包扫描配置 --- 添加@ConfigurationScan注解替换<context:component-scan base-package="">
        • @Configuration
        • @ComponentScan("com.smallstu") --- 设定扫描路径
        • public class SpringConfig{
        • }
        • ---------------------------------------------------------------------
        • 设置扫描路径注解只能使用一次,多个数据使用数组格式
        • @ComponentScan({"com.smallstu.dao","com.smallstu.service"})
      • 初始化容器方式
        • 加载配置文件初始化容器
          • ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
        • 加载配置类初始化容器
          • AnnotationConfigApplicationContext app = new AnnotationConfigApplicationContext(SpringConfig.class);
      • 测试
        • AnnotationConfigApplicationContext app = new AnnotationConfigApplicationContext(SpringConfig.class);
        • BookDao bookDao = (BookDao) app.getBean("bookDao");
        • System.out.println(bookDao);
        • -------------------------------------------------------------------
        • BookService bookService = (BookService) app.getBean("serviceDao");
        • System.out.println(bookService);
      • @Configuration
        • 类型:类注解
        • 位置:类定义上方
        • 作用:设置该类为Spring配置类
        • 属性:value(默认):定义bean的id
      • @ConfigurationScan
        • 类型:类注解
        • 位置:类定义上方
        • 作用:设置Spring配置类扫描路径,用于加载注解格式定义的bean
        • 属性:value(默认):扫描路径,逐层向下扫描
  • 注解开发bean作用范围与生命周期管理
    • 环境准备
      • 创建Maven项目
      • 添加Spring依赖
      • 添加配置类SpringConfig
        • @Configuration
        • @ConfiguraitonScan("com.smallstu")
        • public class SpringConfig{
        • }
      • 创建BookDao、BookDaoImpl类
        • public interface BookDao{
        • public void save();
        • }
        • --------------------------------------------------------------------
        • @Repository
        • public class BookDaoImpl implements BookDao{
        • public void save(){
        • System.out.println("book dao save");
        • }
        • }
      • 测试
        • AnnotationConfigApplicationContext app = new AnnotationConfigApplicationContext(SpringConfig.class);
        • BookDao bookDao = app.getBean(BookDao.class);
        • System.out.println(bookDao);
    • bean的作用范围
      • 默认情况下bean是单例的,设为非单例注解
        • @Repository
        • @Scope("prototype")
        • public class BookDaoImpl implements BookDaoImpl{
        • public void save(){
        • System.out.println("book dao save");
        • }
        • }
      • @Scope
        • 类型:类注解
        • 位置:类定义上方
        • 作用:设置该类对象作用范围,可用于设置创建出的bean是否为单例对象
        • 属性:value(默认):定义bean的作用范围(单例singleton,非单例prototype)
    • bean的生命周期
      • 在BookDaoImpl中添加两个方法(inti和destory) --- 方法名可自定义
        • @Repository
        • public class BookDaoImpl implements BookDao{
        • public void save(){System.out.println("book dao save");}
        • public void init(){System.out.println("init");}
        • public void destory(){System.out.println("destory");}
        • }
      • 在对应方法上添加@PostConstruct和@PreDestory注解标识初始化方法和销毁方法
        • @Repository
        • public class BookDaoImpl implements BookDao{
        • public void save(){System.out.println("book dao save");}
        • @PostConstruct --- 构造方法之后执行
        • public void init(){System.out.println("init");}
        • @PreDestory --- 销毁方法之前执行
        • public void destory(){System.out.println("destory");}
        • }
        • 说明:销毁方法只有在容器关闭时才会执行
      • @PostConstruct和@PreDestory注解找不到
        • 原因:JDK9以后将javax.annotation包移除
        • 解决:添加依赖
          • <dependency>
            • <groupId>javax.annotation<groupId/>
            • <artifactId>javax.annotation-api</artifactId>
            • <version>1.3.2</version>
          • <dependency/>
      • @PostConstruct
        • 类型:方法注解
        • 位置:方法上
        • 作用:设置该方法为初始化方法
        • 属性:无
      • @PreDestory
        • 类型:方法注解
        • 位置:方法上
        • 作用:设置该方法为销毁方法
        • 属性:无
    • 小结:bean属性与注解对应关系
      • id相当于@Component、@Controller、@Service、@Repository
      • scope相当于@Scope
      • init-method相当于@PostConstruct
      • destory-method相当于@PreDestory
      • class相当于注解所处的位置
  • 注解开发依赖注入
    • 自动装配的注解实现
      • 环境准备
        • 创建Maven项目
        • 添加Spring依赖
        • 添加配置类SpringConfig.java
          • @Configuration
          • @ComponentScan("com.smallstu")
          • public class SpringConfig{
          • }
        • 创建BookDao、BookDaoImpl、BookService、BookServiceImpl
          • public interface BookDao{
          • public void save();
          • }
          • @Repository
          • public class BookDaoImpl implements BookDao{
          • public void save(){System.out.println("book dao save");}
          • }
          • --------------------------------------------------------------
          • public interface BookService{
          • public void save();
          • }
          • @Service
          • public class BookServiceImpl implements BookService{
          • private BookDao bookDao;
          • public void setBookDao(BookDao bookDao){this.bookDao = bookDao;}
          • public void save(){
          • System.out.println("book service save");
          • bookDao.save();
          • }
          • }
        • 测试
          • AnnotationConfigApplicationContext app = new AnnotationConfigApplicationContext(SpringConfig.class);
          • BookService bookService = app.getBean(BookService.class);
          • bookService.save();
        • 问题
          • BookServiceImpl类中添加了BookDao的属性和setter方法,但没有配置注入BookDao
          • 导致bookDao调用方法时报空指针异常
      • 注解实现按照类型注入
        • 在BookServiceImpl类的bookDao属性上添加@Autowired注解
          • @Service
          • public class BookServiceImpl implements BookService{
          • @Autowired
          • private BookDao bookDao;
          • //public void setBookDao(BookDao bookDao){this.bookDao = bookDao;}
          • public void save(){
          • System.out.println("book service save");
          • bookDao.save();
          • }
          • }
        • 说明
          • @Autowired可以写在属性上,也可以写在setter方法上,推荐写在属性上删除setter方法
          • setter方法为什么可以删除
            • 自动装配基于反射设计创建对象并通过暴力反射为私有属性进行设值
            • 普通反射只能获取public修饰的内容
            • 暴力反射除了获取public修饰的内容还可以获取private修饰的内容
            • 所以此处无需提供setter方法
        • @Autowired是按照类型注入,如果BookDao接口有多个实现类会报错
          • 原因:按照类型注入无法区分到底注入了哪个对象
          • 解决方案:按照名称注入
        • 给两个Dao分别起个名字
          • @Repository("bookDao1")
          • public class BookDaoImpl1 implements BookDao{
          • public void save(){System.out.println("book dao save1");}
          • }
          • ----------------------------------------------------------------
          • @Repository("bookDao2")
          • public class BookDaoImpl2 implements BookDao{
          • public void save(){System.out.println("book dao save2");}
          • }
      • 注解实现按照名称注入
        • @Autowired
          • 类型:属性注解或方法注解或方法形参注解
          • 位置:属性定义上方或标准set方法上方或类set方法上方或方法形参前面
          • 作用:为引用类型属性设置值
          • 属性:required:true/false,定义该属性是否允许为null
        • @Qualifier
          • 类型:属性注解或方法注解或方法形参注解
          • 位置:属性定义上方或标准set方法上方或类set方法上方或方法形参前面
          • 作用:为引用类型属性设置值
          • 属性:required:true/false,定义该属性是否允许为null
      • 简单数据类型注入
        • BookDaoImpl类中添加name属性
          • @Repository("bookDao")
          • public class BookDaoImpl implements BookDao{
          • private String name;
          • public void save(){System.out.println("book dao save");}
          • }
        • 在属性上添加@Value属性
          • @Repository("bookDao")
          • public class BookDaoImpl implements BookDao{
          • @Value("smallstu")
          • private String name;
          • public void save(){System.out.println("book dao save" + name);}
          • }
          • 说明:数据类型务必匹配
  • 注解读取properties配置文件
    • @Value一般被用在从properties配置文件中读取内容
    • 配置类上添加@PropertySource注解
      • @Configuration
      • @ComponentScan("comsmallstu")
      • @PropertySource("jdbc.properties")
      • public class SpringConfig{
      • }
    • 使用Value注解读取配置文件内容
      • @Repository("bookDao")
      • public class BookDaoImpl implements BookDao{
      • @Value("${name}")
      • private String name;
      • public void save(){System.out.println("book dao save" + name);}
      • }
    • 说明
      • 如果读取的properties配置文件有多个,可以使用@PropertySource的属性来指定多个
      • @PropertySource({"jdbc.properties","xxx.properties"})
      • @PropertySource注解中不支持使用通配符*
      • @PropertySource注解属性中可以把classpath:加上,代表从当前项目的根路径查找文件
  • 注解开发管理第三方bean
    • 环境准备
      • 创建Maven项目
      • 添加Spring依赖
      • 创建SpringConfig配置类
        • public class SpringConfig{
        • }
      • 创建BookDao、BookDaoImpl类
        • public interface BookDao{
        • public void save();
        • }
        • @Respority
        • public class BookDaoImpl implements BookDao{
        • public void save(){System.out.println("book dao save");}
        • }
      • 测试
        • AnnotationConfigApplicationContext app = new AnnotationConfigApplicationContext(SpringConfig.class);
    • 注解管理第三方bean
      • 添加第三方依赖
        • <dependency>
        • <groupId>com.alibaba</groupId>
        • <artifactId>druid</artifactId>
        • <version>1.1.16</version>
        • </dependency>
      • 配置类中添加方法,方法返回值为要创建的bean对象类型
        • @Configuration
        • public class SpringConfig{
        • public DataSource dataSource(){
        • DruidDataSource ds = new DruidDataSource();
        • ds.setDriverClassName("com.mysql.jdbc.Driver");
        • ds.setUrl("jdbc:mysql://localhost:3306/smallstu");
        • ds.setUsername("root");
        • ds.setPassword("000000");
        • return ds;
        • }
        • }
      • 在方法上添加@Bean注解 --- 将方法的返回值作为Spring管理的一个bean对象
        • @Configuration
        • public class SpringConfig{
        • @Bean
        • public DataSource dataSource(){
        • DruidDataSource ds = new DruidDataSource();
        • ds.setDriverClassName("com.mysql.jdbc.Driver");
        • ds.setUrl("jdbc:mysql://localhost:3306/smallstu");
        • ds.setUsername("root");
        • ds.setPassword("000000");
        • return ds;
        • }
        • }
      • 说明
        • 不能使用DataSource ds = new DruidDataSource();
        • 因为DataSource接口中没有对应的setter方法来设置属性
      • 测试
        • AnnotationConfigApplicationContext app = new AnnotationConfigApplicationContext(SpringConfig.class);
        • DataSource dataSource = app.getBean(DataSource.class);
        • System.out.println(dataSource);
  • 引入外部配置类
    • 使用包扫描引入
      • 在Spring配置类上添加包扫描
        • @Configuration
        • @ComponentScan("com.smallstu.config")
        • public class SpringConfig{
        • }
      • 在外部配置类上添加@Component注解(且放在com.smallstu.config包下)
        • @Configuration
        • public class JdbcConfig{
        • @Bean
        • public DataSource dataSource(){
        • DruidDataSource ds = new DruidDataSource();
        • ds.setDriverClassName("com.mysql.jdbc.Driver");
        • ds.setUrl("jdbc:mysql://localhost:3306/smallstu");
        • ds.setUsername("root");
        • ds.setPassword("000000");
        • return ds;
        • }
    • 使用@Import导入
      • 去除JdbcConfig类上的注解
        • public class JdbcConfig{
        • @Bean
        • public DataSource dataSource(){
        • DruidDataSource ds = new DruidDataSource();
        • ds.setDriverClassName("com.mysql.jdbc.Driver");
        • ds.setUrl("jdbc:mysql://localhost:3306/smallstu");
        • ds.setUsername("root");
        • ds.setPassword("000000");
        • return ds;
        • }
      • 在SpringConfig配置类中引入
        • @Configuration
        • @Import(JdbcConfig.class)
        • public class SpringConfig{
        • }
      • 注意
        • 扫描注解可以移除
        • @Import参数需要的是一个数组,可以引入多个配置类
        • @Import注解在配置类中只能写一次
      • @Bean
        • 类型:方法注解
        • 位置:方法定义上方
        • 作用:设置该方法的返回值作为Spring管理的bean
        • 属性:value(默认):定义bean的id
      • @Import
        • 类型:类注解
        • 位置:类定义上方
        • 作用:导入配置类
        • 属性:value(默认):定义导入的配置类类名(当配置类有多个时使用数组格式一次性导入多个配置类)
  • 注解开发为第三方bean注入资源
    • 简单数据类型
      • 需求分析 --- 如何优化
        • public class JdbcConfig{
        • @Bean
        • public DataSource dataSource(){
        • DruidDataSource ds = new DruidDataSource();
        • ds.setDriverClassName("com.mysql.jdbc.Driver");
        • ds.setUrl("jdbc:mysql://localhost:3306/smallstu");
        • ds.setUsername("root");
        • ds.setPassword("000000");
        • return ds;
        • }
      • 注入简单数据类型
        • 类中提供四个属性
          • public class JdbcConfig{
          • private String driver;
          • private String url;
          • private String userName;
          • private String password
          • @Bean
          • public DataSource dataSource(){
          • DruidDataSource ds = new DruidDataSource();
          • ds.setDriverClassName("com.mysql.jdbc.Driver");
          • ds.setUrl("jdbc:mysql://localhost:3306/smallstu");
          • ds.setUsername("root");
          • ds.setPassword("000000");
          • return ds;
          • }
        • Value注解引入值
          • public class JdbcConfig{
          • @Value("com.mysql.jdbc.Driver")
          • private String driver;
          • @Value("jdbc:mysql://localhost:3306/smallstu")
          • private String url;
          • @Value("root")
          • private String userName;
          • @Value("000000")
          • private String password
          • @Bean
          • public DataSource dataSource(){
          • DruidDataSource ds = new DruidDataSource();
          • ds.setDriverClassName(driver);
          • ds.setUrl(url);
          • ds.setUsername(userName);
          • ds.setPassword(password);
          • return ds;
          • }
        • 扩展:将数据库连接四要素提取到jdbc.properties配置文件中
          • 使用@PropertySource加载jdbc.properties配置文
          • 修改@Value注解属性的值,将其修改为${key}
    • 引用数据类型
      • 需求分析
        • 如何在构建DataSource对象同时把BookDao对象注入进方法内让其使用
          • public class JdbcConfig{
          • @Bean
          • public DataSource dataSource(){
          • DruidDataSource ds = new DruidDataSource();
          • ds.setDriverClassName("com.mysql.jdbc.Driver");
          • ds.setUrl("jdbc:mysql://localhost:3306/smallstu");
          • ds.setUsername("root");
          • ds.setPassword("000000");
          • return ds;
          • }
      • 注入引用数据类型
        • 在SpringConfig中扫描BookDao
          • @Configuration
          • @ComponentScan("com.smallstu.dao")
          • @Import(JdbcConfig.class)
          • public class SpringConfig{
          • }
        • 在JdbcConfig上添加参数
          • @Bean
          • public DataSource dataSource(BookDao bookDao){
          • System.out.println(bookDao);
          • DruidDataSource ds = new DruidDataSource();
          • ds.setDriverClassName(driver);
          • ds.setUrl(url);
          • ds.setUsername(userName);
          • ds.setPassword(password);
          • return ds;
          • }

Spring整合Mybatis

  • 准备数据表
    • create table account(
    • id int primary key auto_increment,
    • name varchar(20),
    • money double
    • );
  • 添加项目依赖
    • <dependency>
      • <groupId>org.springframework</groupId>
      • <artifactId>spring-context</artifactId>
      • <version>5.2.10.RELEASE</version>
    • </dependency>
    • <dependency>
      • <groupId>com.alibaba</groupId>
      • <artifactId>druid</artifactId>
      • <version>1.1.16</version>
    • </dependency>
    • <dependency>
      • <groupId>org.mybatis</groupId>
      • <artifactId>mybatis</artifactId>
      • <version>3.5.6</version>
    • </dependency>
    • <dependency>
      • <groupId>mysql</groupId>
      • <artifactId>mysql-connector-java</artifactId>
      • <version>5.1.47</version>
    • </dependency>
  • 创建实体类
    • public class Account implements Serializable{
    • private Integer id;
    • private String name;
    • private Double money;
    • }
  • 创建dao接口
    • public interface AccountDao {
    • @Insert("insert into account(name,money) values(#{name},#{money})")
    • void save(Account account);
    • -------------------------------------------------------
    • @Delete("delete from account where id = #{id}")
    • void delete(Integer id);
    • -------------------------------------------------------
    • @Update("update account set name = #{name}, money = #{money} where id = #{id}")
    • void update(Account account);
    • -------------------------------------------------------
    • @Select("select * from account")
    • List<Account> findAll();
    • -------------------------------------------------------
    • @Select("select * from account where id = #{id}")
    • Account findById(Integer id);
    • }
  • 创建Service接口和实现类
    • public interface AccountService {
    • void save(Account account);
    • void delete(Integer id);
    • void update(Account account);
    • List<Account> findAll();
    • Account findById(Integer id);
    • }
    • -------------------------------------------------------
    • @Service
    • public class AccountServiceImpl implements AccountService {
    • -------------------------------------------------------
    • @Autowired
    • private AccountDao accountDao;
    • public void save(Account account) {
    • accountDao.save(account);
    • }
    • -------------------------------------------------------
    • public void update(Account account){
    • accountDao.update(account);
    • }
    • public void delete(Integer id) {
    • accountDao.delete(id);
    • }
    • public Account findById(Integer id) {
    • return accountDao.findById(id);
    • }
    • public List<Account> findAll() {
    • return accountDao.findAll();
    • }
    • }
  • 添加jdbc.properties文件
    • jdbc.driver=com.mysql.jdbc.Driver
    • jdbc.url=jdbc:mysql://localhost:3306/smallstu?useSSL=false
    • userSSL=false --- 关闭Mysql的SSL安全连接
    • jdbc.username=root
    • jdbc.password=000000
  • 添加Mybatis核心配置文件
    • <configuration>
      • <!--读取外部properties配置文件-->
      • <properties resource="jdbc.properties"></properties>
      • <!--别名扫描的包路径-->
      • <typeAliases>
        • <package name="com.smallstu.domain"/>
      • </typeAliases>
      • <!--数据源-->
      • <environments default="mysql">
      • <environment id="mysql">
        • <transactionManager type="JDBC"></transactionManager>
        • <dataSource type="POOLED">
          • <property name="driver" value="${jdbc.driver}"></property>
          • <property name="url" value="${jdbc.url}"></property>
          • <property name="username" value="${jdbc.username}"></property>
          • <property name="password" value="${jdbc.password}"></property>
        • </dataSource>
      • </environment>
      • </environments>
      • <!--映射文件扫描包路径-->
      • <mappers>
        • <package name="com.smallstu.dao"></package>
      • </mappers>
    • </configuration>
  • 测试
    • public class App {
    • public static void main(String[] args) throws IOException {
    • SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
    • InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml.bak");
    • SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(inputStream);
    • SqlSession sqlSession = sqlSessionFactory.openSession();
    • AccountDao accountDao = sqlSession.getMapper(AccountDao.class);
    • Account ac = accountDao.findById(1);
    • System.out.println(ac);
    • sqlSession.close();
    • }
    • }
  • 说明
    • 真正需要交给Spring管理的是SqlSessionFactory

        

        

                

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值