Spring IoC学习笔记

一、Spring简介

1.Spring是什么?

    Spring是一个开源的容器框架,其中有两个重要的特性分别为

  • 控制反转(IoC)
  • 面向切面(AOP)

2.为什么使用Spring

  • 可以降低组件之间的耦合度,实现各层次间的解耦
    Controller-->Service-->Dao
  • 让代码的结构变得更好
    面向接口编程
    高低原则:高内聚,低耦合
    开闭原则:对扩展开放、对修改关闭
  • 提供了许多支持
    提供了辅助类,如:JdbcTemplate、HibernateTemplate、StringUtils、CollectionUtils、StreamUtils等
    提供了各种服务,如事务管理服务、消息服务等
    提供了单例模式
    提供了AOP技术
  • 对主流框架提供了集成支持
    集成MyBatis、Hibernate、JPA、Struts等

3.Spring体系结构

Spring体系结构图

二、核心概念

1.IoC

  • 控制反转(Inversion of Control)
public class UserServiceImpl{
    //User由Service创建并维护
    private UserDao userDao = new UserDaoImpl();
    
    public void regist(User user){
        userDao.save(user);
    }
}

是指本身不负责依赖对象的创建及维护,把依赖对象的创建和维护交给外部容器来做,这样控制权就发生了转移,控制权转移就是控制反转。

外部容器/IoC容器:存放对象(bean)的容器。

2.DI

  • 依赖注入(dependency injection)
public class UserServiceImpl{
    //User由Service创建并维护
    private UserDao userDao;
    
    //让容器将创建好的对象注入到Service中
    public void setUserDao(UserDao userDao){
        this.userDao = userDao;
    }
    
    public void regist(User user){
        userDao.save(user);
    }
}

是指在运行期,由外部容器动态的将对象注入到组件中

三、第一个Spring程序

1.添加jar包

添加spring-core、spring-beans、spring-context、spring-expresion

  

    
      org.springframework
      spring-core
      5.0.8.RELEASE
    

    
      org.springframework
      spring-beans
      5.0.8.RELEASE
    

    
      org.springframework
      spring-context
      5.0.8.RELEASE
    

    
      org.springframework
      spring-expression
      5.0.8.RELEASE
    

  

2.核心配置文件

用来进行bean的配置,文件名字自定义,一般默认为applicationContext.xml


创建Spring配置文件

2.1 在applicationContext.xml中配置bean

    
    

2.2 在类中加载配置文件并获取bean然后调用方法

public class Test {
    public static void main(String[] args) {
        //传统的调用方式
//        new HelloSpring().show();

        //使用Spring方式调用
        //1.获取IoC容器,读取配置文件初始化Spring上下文
        ApplicationContext ac = new ClassPathXmlApplicationContext("/ioc01/applicationContext.xml");
        //2.根据id从容器中获取bean
        HelloSpring helloSpring = (HelloSpring) ac.getBean("helloSpring");
        //3.调用方法
        helloSpring.show();
    }
}
运行效果图

问题:
调用方法虽然成功,但是并没有给name属性进行赋值
解决:
使用DI进行注入



    

运行效果图

注意:

  • 使用DI时一定要为私有属性生成set方法
  • property标签中的name名一定要与生成的set方法的名字相同(首字母要小写)

四、IoC容器的类型

  • applicationContext
    ClassPathXmlApplicationContext
    FileSystemXmlApplicationContext
    使用方法:
//ApplicationContext
//类路径下加载
ApplicationContext ac = new ClassPathXmlApplicationContext("ioc03/applicationContext.xml");
//文件系统加载
ApplicationContext ac1 = new FileSystemXmlApplicationContext("D:/applicationContext.xml");
//获取bean
SpringBean springBean = (SpringBean) ac.getBean("springBean");
//输出
System.out.println(springBean);
  • BeanFactory
    使用方法:
//BeanFactory
BeanFactory bf = new XmlBeanFactory(new ClassPathResource("ioc03/applicationContext.xml"));
BeanFactory bf1 = new XmlBeanFactory(new FileSystemResource("D:/applicationContext.xml"));
SpringBean springBean1 = (SpringBean) bf.getBean("springBean");
System.out.println(springBean1);

五、数据的装配

1.什么是数据的装配

为bean中的属性注入值,被称为数据装配,可以装配不同类型的值

2.简单类型(共19种)--->使用value进行装配

八种基本数据类型及包装类
byte short int long float double char boolean
Byte Short Integer Long Float Double Character Boolean

String Class Resource

3.其他bean的引用--->使用ref进行装配


    



    

3.1 集合类型

3.1.1 数组



    
        1
        2
        5
    

3.1.2 List



 
     
     
     
     
     
         
     
     
         
     
 

3.1.3 Set


    
        
        
        
        
        
            
        
        
            
        
    

3.1.4 Map


    
        
    

3.1.5 properties


    
        zhangsan
        123456
    

3.1.6 null类型


    

六、bean的生命周期

1.生命周期各阶段

代码块-->构造方法-->set方法-->就绪-->使用-->从容器中销毁

  • 问题:在测试类中获取bean的时候希望把name可以转换成大写。
  • 解决:在set方法中对name进行大写转换。
public void setName(String name) {
    this.name = name.toUpperCase();
}

2.初始化方法/销毁方法

2.1 初始化方法学习

  • 问题:在测试类中调用getName方法时希望得到name_sex的格式
  • 解决:需要在数据装配完成和就绪状态之间添加一个方法。所以在SpringBean类中创建方法,将当前的名字进行转换并追加性别,然后在Spring配置文件中添加init-method属性并指定方法名。
    代码块-->构造方法-->set方法-->初始化方法-->就绪-->使用-->从容器中销毁
//初始化方法
public void init(){
    this.name = this.name.toUpperCase()+"_"+this.sex.toUpperCase();
}

    
    

2.2 销毁方法的学习

代码块-->构造方法-->set方法-->就绪-->使用-->销毁方法-->从容器中销毁

ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("ioc07/applicationContext.xml");
    SpringBean springBean = (SpringBean) ac.getBean("springBean");
    System.out.println(springBean.getName());
    
    // 销毁容器
    // ac.destroy();
    
    // 代码执行完后,销毁容器
    ac.registerShutdownHook();

七、实例化bean的方式

可以通过多种方式创建对象:

  • 构造方法,无参、有参
  • 静态工厂,无参、有参(静态方法)
  • 实例工厂,无参、有参(非静态方法)

1.构造方法



    
    
    




    
    
    

2.静态工厂





    




    

3.实例工厂






    




    

注意:实例化带参工厂的时候,需要使用setXxx("")的方式进行赋值

八、实例化bean的时机

1.ApplicationContext

在加载Spring配置文件时对bean初始化
优点:调用getBean方法时已经初始化完成,可以直接使用比较方便
缺点:因为没有对这个bean进行操作就对bean进行了实例化,所以造成了内存的浪费。
注意:也可以在bean标签中使用laze-init=true设置为调用方法时才初始化。

2.BeanFactory

在调用getBean方法时对bean进行初始化
优点:在调用getBean方法时才进行实例化,可以节约内存。
缺点:在调用getBean方法时才去实例化,比较费时,不方便。

九、bean的作用域

在IoC容器中同一个类默认只有一个bean,也就是单例的
问题:多线程访问时,单例模式下是不安全的。
解决1:可以在bean标签中将scope设置为prototype


    

解决2:可以将属性设置为局部变量

public String getName(String name) {
    return name;
}
  • 注意:在单例模式下,Spring配置文件加载完成就会对bean进行实例化,但是在非单例模式下,只有调用bean的时候才会进行实例化。

十、继承配置

  • 简介
    用来简化代码,减少配置

  • 用法

    • 用法1:不同的子bean类继承自父bean


    



    
    



    
    

  • 用法2:相同的子bean类继承自父bean


    



    
    



    
    

十一、自动装配

1.简介

IoC容器可以根据bean的名称、类型、或构造方法自动进行注入,称为自动装配。
只适用于其他bean的引用

2.配置

通过bean标签中的autowire属性进行注入,默认情况下为default

  • 1.default:不进行自动装配,和no是同样的作用
  • 2.byName:根据属性名进行自动装配(查找与属性名相同的bean)
  • 3.byType(推荐):根据属性的类型进行自动装配(查找与属性类型相同的bean)
  • 4.constructor:根据构造方法自动装配(先按byName方式进行装配,如果没有查找到对应的属性名则按照byType方式进行装配)
    注意:此时可以不要setXxx('')方法
    
    
        
    

    
        
    

十二、在bean中获取IoC容器

定义一个IoC容器的工具类
步骤:

  • 1.获取IoC容器
  • 2.在Spring配置文件中配置ApplicationContextHolder
  • 3.在ApplicationContextHolder中创建获取bean的方法
  • 4.在工具bean中通过ApplicationContextHolder获取bean并获取属性
  • 5.在测试类中调用工具bean

十三、FactoryBean

1.简介

Spring中有两种类型的bean

  • 普通bean,返回的是bean本身的对象。
  • 工厂bean,即FactoryBean
    应用场景:如果普通的bean的配置比较复杂,在配置文件中定义时步骤比较多,此时可以使用FactoryBean

2.定义FactoryBean

步骤:

  • 1.定义一个类,实现FactoryBean接口
  • 2.将该bean添加到IoC容器中
  • 3.获取到FactoryBean的对象
    注意:该Bean返回的并不是FactoryBean类型的对象,而是getObject方法的返回值类型的对象
  • 实现
/**
 * 该FactoryBean是用来生成PreparedStatement的
 */
public class PreparedStatementFactoryBean implements FactoryBean{

    //生成实例的过程
    @Override
    public PreparedStatement getObject() throws Exception {
        //加载驱动
        Class.forName("com.mysql.jdbc.Driver");
        //获取连接对象
        Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/project", "root", "root");
        //获取发送器
        PreparedStatement ps = conn.prepareStatement("select * from t_user");
        return ps;
    }

    //生成实例的类型
    @Override
    public Class getObjectType() {
        return PreparedStatement.class;
    }

    //生成的实例是否为单例
    @Override
    public boolean isSingleton() {
        return true;
    }
}

十四、Resource类

1.简介

本质就是java.io.File的封装

根据资源位置的不同,提供了不同的实现类,用来快速获取文件资源

  • FileSystemResource
  • ClassPathResource
  • UrlResource
  • InputResource

2.基本用法

ApplicationContext ac = new ClassPathXmlApplicationContext("ioc21/applicationContext.xml");
Resource resource = new FileSystemResource("D:/a.txt");
//Resource resource = new ClassPathResource("ioc21/a.txt");
System.out.println(resource.getFilename());
System.out.println(resource.contentLength());
System.out.println(resource.exists());
//获取输入流
InputStream inputStream = resource.getInputStream();
//使用工具类进行文件的复制
StreamUtils.copy(inputStream,new FileOutputStream("D:/b.txt"));

装配Resource


    

十五、后(置)处理器

1.两种后处理器

  • Bean后处理器,实现BeanPostProcessor接口。
  • BeanFactory后处理器,实现BeanFactoryPostProcessor接口,也称之为容器后处理器。

2.BeanPostProcessor

2.1 简介

Bean后处理器用来对bean的功能进行增强和扩展,对IoC容器中的所有bean都有效。
时机: 执行初始化方法之前和之后
bean的生命周期:
代码块-->构造方法-->set方法-->初始化之前-->初始化方法-->初始化之后-->就绪-->使用-->从容器中销毁

2.2 实现步骤

  • 定义一个类,实现BeanPostProcessor接口
  • 将该后处理器添加到IoC容器中

3.BeanFactoryPostProcessor

3.1 简介

容器后处理器在bean创建之前,修改bean的定义属性
bean的生命周期:
BeanFactoryPostProcessor-->代码块-->构造方法-->set方法-->初始化之前-->初始化方法-->初始化之后-->就绪-->使用-->从容器中销毁

3.2 实现步骤

  • 定义一个类,实现BeanFactoryPostProcessor
  • 将容器后处理器添加到IoC容器中
  • 定义属性编辑器PropertyEditor(转换器),实现PropertyEditor接口或继承PropertyEditorSupport父类
  • 在容器后处理器中注册属性编辑器

你可能感兴趣的:(Spring IoC学习笔记)