将对象的创建初始化销毁等操作交给 Spring 容器来管理

本文以Student 类为例,定义如下:

public class Student {
    public String name;
    public Integer number;
    public boolean sex;
	//..constructor,getter and setter
}

一. 创建一个简单的IOC应用

  1. 引入maven依赖

    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.1.9.RELEASE</version>
        </dependency>
    </dependencies>
    
  2. 📂resources 下创建一个 spring 的配置文件ioc.xml 引入了Studentid为该 bean 唯一标识符,通常 id 与 name一样

    <?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 class="com.xu.ioc.Student" id="student"/>
    </beans>
    
  3. 调用容器中的 bean

    public class Person {
        public static void main(String[] args) {
            ClassPathXmlApplicationContext ctx =new ClassPathXmlApplicationContext("ioc.xml");
            Student student = (Student) ctx.getBean("student");
            System.out.println(student);
        }
    }
    /*
    输出:
    Student无参构造执行
    com.xu.ioc.Student@27efef64
    */
    
    • 获取配置文件的方法:
      • ClassPathXmlApplicationContext 从 classpath 下查找配置文件
      • FileSystemXmlApplicationContext 从操作系统路径下去寻找配置文件
    • 获取 Bean 的方法:
      • 通过idnamectx.getBean("student")
      • 通过类名:ctx.getBean(Student.class) (不推荐,当一类有多个bean时会报错)

二. Bean 的属性注入

1. 通过构造方法

需要Student 类中已定义好构造函数

<bean class="com.xu.ioc.Student" id="student">
    <constructor-arg index="0" value="LiHua"/>
    <constructor-arg index="1" value="119"/>
    <constructor-arg index="2" value="true"/>
</bean>

或直接用 name 来指定

<bean class="com.xu.ioc.Student" id="student">
    <constructor-arg name="name" value="LiHua"/>
    <constructor-arg name="number" value="119"/>
    <constructor-arg name="sex" value="true"/>
</bean>

2. 通过 set 方法注入

==属性值==并不是类中定义的属性名,而是通过set方法分析得到的属性名

<bean class="com.xu.ioc.Student" id="student">
    <property name="name" value="LiHua"/>
    <property name="number" value="119"/>
    <property name="sex" value="true"/>
</bean>

3. 其他复杂属性注入

  • 对象注入:通过 ref 引用对象

    <bean class="com.xu.User" id="user">
        <property name="cat" ref="cat"/>
    </bean>
    <bean class="com.xu.Cat" id="cat">
        <property name="name" value="小白"/>
        <property name="color" value="白色"/>
    </bean>
    
  • 数组注入:array 节点,也可以被list节点代替

    <bean class="com.xu.User" id="user">
        <property name="cat" ref="cat"/>
        <property name="favorites">
            <array>
                <value>足球</value>
                <value>篮球</value>
                <value>乒乓球</value>
            </array>
        </property>
    </bean>
    <bean class="com.xu.Cat" id="cat">
        <property name="name" value="小白"/>
        <property name="color" value="白色"/>
    </bean>
    
  • Map 注入:

    <property name="map">
        <map>
            <entry key="age" value="99"/>
            <entry key="name" value="xu"/>
        </map>
    </property>
    
  • Properties 注入:

    <property name="info">
        <props>
            <prop key="age">99</prop>
            <prop key="name">xu</prop>
        </props>
    </property>
    

三. Bean 注册

1.Java 配置

通过注解和配置类实现,首先定义配置类JavaConfig

@Configuration
public class JavaConfig {
    @Bean
    Student sayHello() {
        return new Student();
    }
}

@Configuration 表示这个类不是一个普通类,而是一个配置类,它的作用相当于 applicationContext.xml@Bean 注解,将这个方法的 ==返回值== 注入 Spring 容器

接着在主方法中添加配置类:通过AnnotationConfigApplicationContext引入配置类

public class Person {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(JavaConfig.class);
        Student hello = ctx.getBean(SayHello.class);
        System.out.println(hello);
    }
}

2. 自动化配置

添加自动化注解

  • 在 Service 层上,添加注解时,使用 @Service
  • 在 Dao 层,添加注解时,使用 @Repository
  • 在 Controller 层,添加注解时,使用 @Controller
  • 在其他组件上添加注解时,使用 @Component

配置自动化扫描

通过@ComponentScan

对配置类JavaConfig,添加@ComponentScan进行包扫描,然后在主方法中通过AnnotationConfigApplicationContext引入配置类

@Configuration
@ComponentScan(basePackages = "com.xu.javaconfig.service")
//扫描com.xu.javaconfig包下的service类
public class JavaConfig {
}
  • 扫描进容器的bean名称,默认为类名==首字母小写==,可以在注解中定义名称。

  • 可以自定义扫描规则,扫描指定类,如下是不扫描Controller注解进容器

    @Configuration
    @ComponentScan(basePackages = "com.xu.javaconfig",useDefaultFilters = true,excludeFilters = {@ComponentScan.Filter(type = FilterType.ANNOTATION,classes = Controller.class)})
    public class JavaConfig {
    }
    

通过 xml

在 xml 文件中添加:

<context:component-scan base-package="com.xu.javaconfig"/>

主方法中通过ClassPathXmlApplicationContext加载配置文件即可完成注册

同样可以自定义扫描规则:

<context:component-scan base-package="com.xu.javaconfig" use-default-filters="true">
    <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>

对象注入

一般有三种对象注入方式:

  • @Autowired:根据类型查找,要求该类型只能有一个Bean
    • 可与@Qualifier注解配合,达到通过Bean名称查找的效果
  • @Resources:根据定义的Bean名查找
  • @Injected:与@Autowired类似,但需要导入javax.inject.Inject,不常用

四. Bean的生命周期