Spring-ioc基础学习(1):ioc概念,xml配置相关学习

定义

依赖倒置原则(DIP)

具体实现依赖抽象,下层依赖上层

IOC控制反转

我们原本创建对象时可以随意安排创建对象的时机,进行对象创建,但是在引入spring-ioc容器后,对象创建的工作转交给了容器进行,创建对象的控制权在容器手中,由容器控制在什么时机,用什么方式去创建,控制权从开发者手中转交由容器进行操作控制,这就是控制反转的基本概念

DI依赖注入

创建对象时原本是使用new自己创建,而使用spring-ioc后,创建对象的工作转交给spring-ioc容器进行操作,对象的创建是需要依赖spring-ioc容器的注入才行,就是依赖注入的基础概念

IOC是DIP的设计原理,DI是IOC的具体实现

使用IOC带来的好处

  • 解耦
  • 将对象的创建进行集中管理
  • 提高了功能的复用
  • 提高了程序整个体系的可维护性,灵活性,扩展性

IOC配置详情

ApplicationContext接口是Spring IoC容器实现的代表,它负责实例化,配置和组装Bean
继承类图


ApplicationContext

ApplicationContext配置元数据的方式有三种

  • 使用xml

最基础的使用方式,相对繁琐,需要有配置文件支持,一般使用ClassPathXMLApplicationContext进行实例化容器,但是内容最为清晰直观.

  • 使用java注释

Spring 2.5 支持基于注解的元数据配置.使用包扫扫描(context:component‐scan)等功能将被注释的类加载到容器中,还是结合xml文件进行配置.

  • 使用java代码

从 Spring 3.0开始, 由Spring JavaConfig项目提供的功能已经成为Spring核心框架的一部分,你可以使用Java配置来代替XML配置定义外部bean,使用AnnotationConfigApplicationContext进行实例化容器

容器的使用

使用ApplicationContext/BeanFactory接口来进行bean的创建,进行容器对象加载可以使用getBean方法

  • 现阶段一般使用ApplicationContext接口进行对象创建,因其内部有更多的方法封装,其包含所有BeanFactory的方法以及
  • BeanFactory是实现IOC的核心接口,其中IOC的功能都是由BeanFactory定义的,核心为getBean系列方法
  • BeanFactory和ApplicationContext最大的不同是,加载方式,单例作用域下,BeanFactory默认为懒加载,而ApplicationContext是饿加载,需要手动设置才会为懒加载

XML配置的IOC相关功能具体示例和说明

(1)基础准备工作

0.引入依赖,pom.xml中引入spring-context即可将关联的依赖jar都引入其中


            org.springframework
            spring-context
            5.2.6.RELEASE
            compile

1.创建容器对象

xml下容器对象一般使用ClassPathXMLApplicationContext来进行创建容器

常用容器实现类有

  • ClassPathXMLApplicationContext 根据项目路径的xml来配置实例化spring容器
  • FileSystemXmlApplicationContext 根据磁盘路径的xml来配置实例化spring容器
  • AnnotationConfigApplicationContext 根据JavaConfig来配置实例化Spring容器
ApplicationContext ioc =new ClassPathXmlApplicationContext("spring-ioc.xml")

2.定义spring的xml配置文件

spring-ioc.xml配置文件的操作基本都在beans中进行配置,需要引入必要的依赖约束内容(配置文件是自定义名称的并无强制要求,为了明确基础意义,设定为spring-ioc.xml)




3.定义所需示例类,主要有Person,Wife,Child,三个,Wife和Child继承Person,以及一个工厂Person的工厂类

package com.learn.beans;

import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * @author wangxing
 * @version 2020/6/26 16:35 Administrator
 */
public class Person {
    private Integer id;
    private String name;
    private String gender;
    private Date birthday;
    private List  hobbies;
    private Map course;
    private Wife wife;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }
    public void setIdxxx(Integer id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getGender() {
        return gender;
    }

    public void setGender(String gender) {
        this.gender = gender;
    }

    public Date getBirthday() {
        return birthday;
    }

    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }

    public List getHobbies() {
        return hobbies;
    }

    public void setHobbies(List hobbies) {
        this.hobbies = hobbies;
    }

    public Map getCourse() {
        return course;
    }

    public void setCourse(Map course) {
        this.course = course;
    }

    public Wife getWife() {
        return wife;
    }

    public void setWife(Wife wife) {
        this.wife = wife;
    }

    @Override
    public String toString() {
        return "Person{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", gender='" + gender + '\'' +
                ", birthday=" + birthday +
                ", hobbies=" + hobbies +
                ", course=" + course +
                ", wife=" + wife +
                '}';
    }

    public Person() {
        System.out.println(" load person");
    }

    public Person(Integer id, String name, String gender, Date birthday, List hobbies,
                  Map course, Wife wife) {
        this.id = id;
        this.name = name;
        this.gender = gender;
        this.birthday = birthday;
        this.hobbies = hobbies;
        this.course = course;
        this.wife = wife;
    }

    public Person(String name) {
        this.name = name;
    }
    public static Person createPersonFactory(String type){
        if ("wife".equals(type)) {
            return new Wife();
        } else if ("child".equals(type)) {
            return  new Child();
        }else{
            return new Person();
        }
    }
}
package com.learn.beans;

/**
 * @author wangxing
 * @version 2020/6/26 16:38 Administrator
 */
public class Wife extends Person {
    private Integer id;
    private String name;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "Wife{" +
                "id=" + id +
                ", name='" + name + '\'' +
                '}';
    }

    public Wife() {
        System.out.println("load wife"+this);
    }

    public Wife(Integer id, String name) {
        this.id = id;
        this.name = name;
        System.out.println("load wife"+this);
    }
}
package com.learn.beans;

import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;

/**
 * @author wangxing
 * @version 2020/6/26 17:57 Administrator
 */
public class Child extends Person implements InitializingBean, DisposableBean {
    public void initByConfig(){
        System.out.println("通过配置实现的初始化方法");
    }
    public void destroyByConfig(){
        System.out.println("通过配置实现的销毁方法");
    }

    public void destroy() throws Exception {
        System.out.println("通过实现DisposableBean接口实现的销毁方法");
    }

    public void afterPropertiesSet() throws Exception {
        System.out.println("通过实现InitializingBean接口实现的初始化方法");
    }
}
package com.learn.beans.factory;

import com.learn.beans.Child;
import com.learn.beans.Person;
import com.learn.beans.Wife;

/**
 * @author wangxing
 * @version 2020/6/26 17:59 Administrator
 */
public class PersonFactory {
    public Person createPersonFactory(){
        return new Person();
    }
    public Person createPersonFactory(String type){
        if ("wife".equals(type)) {
            return new Wife();
        } else if ("child".equals(type)) {
            return  new Child();
        }else{
            return new Person();
        }
    }
}

(2)学习spring-ioc的基础功能

0.标签定义类基础信息


    
        用来描述一个类是用来做什么的
    

    

bean标签在spring-beans.xsd中的定义


        
            


        
        
            
                
                    
                    
                
            
        
    

bean标签的属性
bean标签的属性定义源码

1.在方法中通过IOC容器进行类加载的方式

/*
1.通过类来获取bean
当配置文件中有多个相同类的配置时会报错,一般使用方法二和三
*/
Pesron user = (User)context.getBean(Pesron.class);
/*
 2.通过xml配置文件中名称来获取bean
需要进行强制转型
*/
Pesron user = (Pesron)context.getBean("user");
/*
3.通过名字+类来获取bean
通过名称和类型两个参数进行确认,保证不会加载错误
*/
Pesronuser = context.getBean("user",Pesron.class);

2.进行类信息的注入
主要有两种注入方式

  • setter方法注入

基于setter方法的依赖注入

  1. 属性必须声明了set方法
  2. name是根据set方法的名字来的 比如方法名字是: setIdxx ‐> name="idxx"
 
        
        

可以使用p:标签来进行注入setter方法,但是不能注入集合

使用p标签需要引入对应标签
xmlns:p="http://www.springframework.org/schema/p"


  • 构造方法注入

基于构造函数的依赖注入

  1. 将会调用自定义构造函数来实例化对象,就不会调用默认的无参构造函数
  2. name是根据构造函数的参数名来的, 比如:User(String idxx) ‐> name="idxx"
  3. name属性可以省略 但是要注意参数的位置
  4. 如果非要把位置错开 可以使用 name 或者 index 或者 type
  5. index 是下标 从0开始
  6. type 在位置错开情况下只能在类型不一样的时候指定才有明显效果

        
        
    

可以使用c:标签来进行构造方法的参数注入

使用c:标签构造方法进行参数注入需要引入对应标签
xmlns:c="http://www.springframework.org/schema/c"


3.各种类型数据的配置方式

标签进行属性配置
标签配置list对象
标签配置set对象
标签配置map对象
使用ref属性进行引用类的配置

 
        
         
        
        
        
            
                阅读
                运动
            
        
        
            
                
                
                
            
        
    

4.控制依赖加载顺序使用bean:depends-on属性来控制加载依赖于某个类

    
    

5.将对象设置为懒加载,使用bean:lazy‐init属性,设置为true时类的加载变更为懒加载,只在调用时进行加载

   

6.自动注入使用bean:autowire属性来进行控制
autowire的值包括四种

  • default/no:不自动装配
  • byType 按照类型进行装配,以属性的类型作为查找依据去容器中找到这个组件,如果有多个类型相同的bean对象,那么会报异常,如果找不到则装配null
  • byName 按照名字进行装配,以属性名作为id去容器中查找组件,进行赋值,如果找不到则装配null
  • constructor:按照构造器进行装配,先按照有参构造器参数的类型进行装配,没有就直接装配null;如果按照类型找到了多个,那么就使用参数名作为id继续匹配,找到就装配,找不到就装配null

//通过将autowire-candidate 属性设置为false,避免对bean定义进行自动装配
//通过将其 元素的primary属性设置为 true,将单个bean定义指定为主要候选项

7.bean的作用域设置使用bean:scope属性进行配置

| singleton | (默认) 每一Spring IOC容器都拥有唯一的实例对象。
| prototype | 一个Bean定义可以创建任意多个实例对象.
| request | 将单个bean定义范围限定为单个HTTP请求的生命周期。 也就是说,每个HTTP请求都有自己的bean实例,它是在单个bean定义的后面创建的。 只有基于Web的Spring ApplicationContext的才可用。
| session | 将单个bean定义范围限定为HTTP Session的生命周期。 只有基于Web的Spring ApplicationContext的才可用。
| application | 将单个bean定义范围限定为ServletContext的生命周期。 只有基于Web的Spring ApplicationContext的才可用。
| websocket | 将单个bean定义范围限定为 WebSocket的生命周期。 只有基于Web的Spring ApplicationContext的才可用。

注意

多线程下单例模式可能会产生线程安全问题,单例模式的对象中控制尽量不要有数据属性,只保留操作方法,如果一定要有属性,那么记得加锁


8.bean的生命周期控制

在对象的加载前和销毁后执行我们定义的方法
实现方式有两种

  • 1使用接口实现的方式来实现生命周期的回调
    初始化方法: 实现接口: InitializingBean 重写afterPropertiesSet方法初始化会自动调用的方法
    销毁的方法: 实现接口: DisposableBean 重写destroy 方法 销毁的时候自动调用方法
    -2 使用指定具体方法的方式实现生命周期的回调,在对应的bean里面创建对应的两个方法init‐method="init" destroy‐method="destroy"

注意:

销毁是在spring容器关闭的时候

package com.learn.beans;

import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;

/**
 * @author wangxing
 * @version 2020/6/26 17:57 Administrator
 */
public class Child extends Person implements InitializingBean, DisposableBean {
    public void initByConfig(){
        System.out.println("通过配置实现的初始化方法");
    }
    public void destroyByConfig(){
        System.out.println("通过配置实现的销毁方法");
    }

    public void destroy() throws Exception {
        System.out.println("通过实现DisposableBean接口实现的销毁方法");
    }

    public void afterPropertiesSet() throws Exception {
        System.out.println("通过实现InitializingBean接口实现的初始化方法");
    }
}


9.向配置文件中引入配置文件使用context:property-placeholder标签

使用context:property-placeholder标签需要引入对应引用
xmlns:context="http://www.springframework.org/schema/context"

定义配置文件

mysql.username=xxx
mysql.password=xxx
mysql.url=jdbc:mysql://192.168.1.150:3306/mall
mysql.driver=com.mysql.jdbc.Driver

xml用引入配置文件,使用第三方类



 
         
         
         
         
     

总结

定义

DIP/IOC/DI

IOC的好处

IOC配置

ApplicationContext的三种配置方式

XML配置方式的学习整理

spring-ioc的xml配置基础标签

1. 
2. bean的注入方式
3. 各类数据类型的装配方式
4. 对类注入进行依赖控制depends-on
5. 将类注入设置为懒加载lazy‐init
6. 自动注入bean:autowire
7. bean的作用域bean:scope
8. bean生命周期控制init‐method="init" destroy‐method="destroy"
9. 引入外部配置文件context:property-placeholder

你可能感兴趣的:(Spring-ioc基础学习(1):ioc概念,xml配置相关学习)