Spring Ioc

发布时间 2023-10-06 23:23:40作者: 3DG
Spring Ioc 容器
什么是Ioc

Ioc即Inversion of control,翻译为控制反转。应用不负责依赖对象的创建维护,转而由外部容器负责。将依赖对象的创建维护的控制交由容器即为控制权的转移,也就是所谓的控制反转--Ioc!
什么是DI

DI(Dependency Injection)依赖注入。向某对象动态地注入其依赖的其它对象的引用。

开发人员无需手动new对象并建立依赖关系,Ioc容器会把实例化对象注入。

依赖注入方式

    构造器注入

    方法注入

    接口注入

Spring Ioc容器

Spring中实现Ioc和DI的组件,用来降低耦合度,简化开发。
Bean

Spring中用来表示组件,可以是任何Java类实例。由Ioc容器管理Bean的生命周期(创建和销毁)

    BeanFactory(Bean 工厂)

BeanFactory 是 Spring 框架最核心的接口,它提供了高级 IoC 的配置机制;BeanFactory 使管理不同类型的 Java 对象成为可能。 BeanFactory 是 Spring 框架的基础设施,属于底层封装组件,专供 Spring 框架内部使用

    ApplicationContext ( 应用上下文 )

ApplicationContex 是建立在 BeanFactory 基础之上,提供了更多面向应用的功能。一般称BeanFactory为IoC容器,而称ApplicationContext 为应用上下文。ApplicationContext 面向 Spring 框架的开发者,属于上层封装组件,专供开发者使用。通过 ApplicationContext 应用上下文实例调用其 getBean() 方法从 IoC 容器中即可获取 Bean 对象实例
启动Ioc容器

有三种方式

    ClassPathXmlApplicationContext(相对路径)

从类路径下的 XML 配置文件中加载上下文定义,把应用上下文定义文件当做类资源

ApplicationContext ctx = new ClassPathXmlApplicationContext(“包路径/beans.xml”)

    FileSystemXmlApplicationContext(绝对路径)

读取文件系统下的 XML 配置文件并加载上下文定义

ApplicationContext ctx = new FileSystemtXmlApplicationContext(“文件路径/beans.xml”)

    XmlWebApplicationContext(web 配置路径)

    读取 Web 应用下的 XML 配置文件并加载上下文定义

初始化和销毁Ioc容器

//初始化(Ioc容器调用)
public void init(){
    System.out.println("调用初始化方法");
}

//销毁(Ioc容器调用)
public void destroy(){
    System.out.println("调用销毁方法");
}

加载Ioc容器

//加载Ioc容器方式一
  ClassPathXmlApplicationContext ioc =
          new ClassPathXmlApplicationContext("ioc.xml");

  //加载Ioc容器方式二
//    FileSystemXmlApplicationContext ioc2 =
//            new FileSystemXmlApplicationContext("E:\\Workout\\Spring001\\src\\main\\resources\\ioc.xml");

装配Bean

装配 Bean 指在 Spring IoC 容器中创建 Bean 组件及建立 Bean 组件之间的依赖关系的过程。(实现 IoC(控制反转)和 DI(依赖注入)) Spring 支持三种装配 Bean 的方式:

    基于 XML 配置装配 Bean

    基于注解装配 Bean

    基于 Java 类装配 Bean

注解装配Bean

<!--开启自动装配注解(默认禁用注解)-->
<context:annotation-config/>

<!--开启自动扫描Bean-->
<context:component-scan base-package="bean"/>

获得Bean

getBean() 两种用法:name:bean的id ;
class:bean的类型(唯一)

Boy boy2 == ioc.getBean(Boy.class);//要求boy类型唯一

Boy boy2 = (Boy)ioc.getBean("boy2");
System.out.println(boy2.getGirl());

IoC 注解

    @Component:标识 Java 类为 Spring Bean 组件(通用注解)

    @Controller:标识三层架构中表现层的 Java 类为 Spring Bean 组件

    @Service:标识三层架构中业务逻辑层的 Java 类为 Spring Bean 组件

    @Repository:标识三层架构中业务持久层的 Java 类为 Spring Bean 组件

DI 注解

    @Autowired:依赖注入

    默认采用byType,byType适用类型唯一。否则使用byName,byName失效则抛出异常,依赖注入的id是属性名.

    常用的有

    基于属性注入

    @Service
    public class Student {
        @Autowired
        private Teacher teacher;
    }

    基于setter方法注入

     @Autowired
        public void setTeacher(Teacher teacher) {
            this.teacher = teacher;
        }

    基于构造器注入

    @Autowired
    public Student( Teacher teacher) {
    ​
        this.teacher = teacher;
    }

    @Resource:使用与 @Autowired 注解相同

    @Qualifer:明确指定需要自动装配的 Bean 组件

     @Qualifier("teacher2") //强制采用byName方式指定Bean的id

手动获取Bean的方式

Spring中,通过ApplicationContext手动获取Bean。

@Componet 默认id为类名(其首字母变为小写)

@Component //等价于 <bean id="teacher" class="bean.Teacher"> 配置
public class Teacher {

    private String name;
    private int age;

}

初始化和销毁Ioc容器

//初始化(Ioc容器调用)
public void init(){
    System.out.println("调用初始化方法");
}

//销毁(Ioc容器调用)
public void destroy(){
    System.out.println("调用销毁方法");
}

一些常用注解
初始化和销毁

通过@Bean(initMethod="init",destoryMethod="destory")方法

<bean id="boy" class="ioc.Boy" scope="singleton"
      init-method="init" destroy-method="destroy">

Java配置类

@Configuration

声明当前类为配置类;

@Bean

注解在方法上,声明当前方法的返回值为一个bean,替代xml中的方式;

@ComponentScan

用于对Component进行扫描;
@Bean的属性支持

@Scope设置类型:

设置Spring容器如何新建Bean实例(方法上,得有@Bean)

① Singleton

一个Spring容器中只有一个bean实例,默认模式

<bean id="boy" class="ioc.Boy" scope="singleton"
      init-method="init" destroy-method="destroy">

② Protetype

调用新建一个bean

<bean id="boy" class="ioc.Boy" scope="prototype"
      init-method="init" destroy-method="destroy">

③ Request

给每个http request新建一个bean

④ Session

给每个http session新建一个bean

⑤ GlobalSession

global http session新建一个Bean实例
@Value

支持如下方式的注入:

    注入普通字符

    注入操作系统属性

    注入表达式结果

    注入其它bean属性

    注入文件资源

    注入网站资源

    注入配置文件

三种情况用法

    ${}找到外部配置参数并赋值

    #{}是SpEL表达式,寻找对应变量内容

    #{}将字符串的值注入

public class Student {
    @Value("Whaler")
    private String name;
    @Value("001")
    private int id;
    }

实例
Config

package bean.java;
import org.springframework.context.annotation.Configuration;

import javax.jws.soap.SOAPBinding;

/*
配置类(Ioc)容器
 */
@Configuration

public class Config {
    @Bean
    public User user(){
        return new User("12WL");
    }
}

TestBean

package bean.java;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class TestBean {
    public static void main(String[] args){
        //通过注解方式加载Ioc容器
        AnnotationConfigApplicationContext ioc = new AnnotationConfigApplicationContext();
        //注册配置类
        ioc.register(Config.class);
        //装配Bean
        ioc.refresh();

        User user = ioc.getBean(User.class);
        System.out.println(user);
    }
}

User

package bean.java;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
    private String name;

}

TestIoc

package ioc;



import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;

/**
 * @author 3DG
 * Ioc容器创建
 */

public class TestIoc {
    public static  void main(String[] args){
        //加载Ioc容器方式一
          ClassPathXmlApplicationContext ioc =
                  new ClassPathXmlApplicationContext("ioc.xml");

   

        //加载Ioc容器方式二
    //    FileSystemXmlApplicationContext ioc2 =
    //            new FileSystemXmlApplicationContext("E:\\Workout\\Spring001\\src\\main\\resources\\ioc.xml");
        //获取Ioc容器的Bean实例(Boy对象实例)
        Boy boy =(Boy) ioc.getBean("boy");//bean的id
        System.out.println(boy.getGirl());

       
        //Boy boy2 == ioc.getBean(Boy.class);要求boy类型唯一

        Boy boy2 = (Boy)ioc.getBean("boy2");
        System.out.println(boy2.getGirl());

        Boy boy3 = (Boy)ioc.getBean("boy2");
        System.out.println(boy);


    }
}

bean_ioc.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<!-- <default-autowire -->

    <!--开启自动装配注解(默认禁用注解)-->
    <context:annotation-config/>

    <!--开启自动扫描Bean-->
    <context:component-scan base-package="bean"/>

    <!--装配单例模式Bean
        factory-method用于调用单例模式的静态方法-->
    <bean id="earth" class="bean.Earth" factory-method="getInstance"/>

    <!--装配内部Bean-->
    <bean id="musician" class="bean.Musician">
        <property name="name" value="朗朗"/>
        <property name="piano">
            <bean class="bean.Piano"/>
        </property>
    </bean>

    <!--装配集合bean-->
    <bean id="chinese" class="bean.Subject"
          p:name="语文" p:score="66"/>
    <bean id="math" class="bean.Subject"
          p:name="数学" p:score="77"/>
    <bean id="english" class="bean.Subject"
          p:name="外语" p:score="88"/>

    <bean id="grade" class="bean.Grade">

        <!--装配List集合-->
        <property name="subjects">
            <list>
                <ref bean="chinese"/>
                <ref bean="math"/>
                <ref bean="english"/>
            </list>
        </property>

        <!--装配Set集合-->
        <property name="classNames">
            <set>
                <value>"1班"</value>
                <value>"2班"</value>
                <value>"3班"</value>
            </set>
        </property>

        <!--装配Map集合-->
        <property name="numbers">
            <map>
                <entry key="1班" value="35"/>
                <entry key="2班" value="37"/>
                <entry key="3班" value="36"/>
            </map>
        </property>
    </bean>

    <!--自动装配bean-->
    <!--
    <bean id="teacher" class="bean.Teacher">
        <property name="name" value="3DG"/>
        <property name="age" value="31"/>
    </bean>
    <bean id="teacher2" class="bean.Teacher">
        <property name="name" value="Lu"/>
        <property name="age" value="35"/>
    </bean>
    -->
    <bean id="student" class="bean.Student" >
        <!--依赖注入的id(即byName的Name)是属性名-->
    <!--    <property name="name" value="Whaler"/>
        <property name="id" value="001"/> -->
<!--    <property name="teacher" ref="teacher"/>    -->
    </bean>


</beans>