跳转至

Spring ApplicationContext 容器

以后你会走很多路,也会遇到很多人,余生没那么长,抬起头挺起胸,你得活的像自己。

1. 介绍

  基于注解的配置,从 Spring 2.5 开始就可以使用注解来配置依赖注入。而不是采用 XML 来描述一个 bean 连线,你可以使用相关类,方法或字段声明的注解,将 bean 配置移动到组件类本身。

  在 XML 注入之前进行注解注入,因此后者的配置将通过两种方式的属性连线被前者重写。

  注解连线在默认情况下在 Spring 容器中不打开。因此,在可以使用基于注解的连线之前,我们将需要在我们的 Spring 配置文件中启用它。所以如果你想在 Spring 应用程序中使用的任何注解,可以考虑到下面的配置文件。

  一旦 被配置后,你就可以开始注解你的代码,表明 Spring 应该自动连接值到属性,方法和构造函数。让我们来看看几个重要的注解,并且了解它们是如何工作的:

限制 描述
重写的可能性 你可以使用总是重写自动装配的 设置来指定依赖关系。
原始数据类型 你不能自动装配所谓的简单类型包括基本类型,字符串和类。
混乱的本质 自动装配不如显式装配精确,所以如果可能的话尽可能使用显式装配。
序号 注解 & 描述
1 @Required 注解应用于 bean 属性的 setter 方法。
2 @Autowired 注解可以应用到 bean 属性的 setter 方法,非 setter 方法,构造函数和属性。
3 @Qualifier通过指定确切的将被连线的 bean,@Autowired 和 @Qualifier 注解可以用来删除混乱。
4 JSR-250 Annotations Spring 支持 JSR-250 的基础的注解,其中包括了 @Resource,@PostConstruct 和 @PreDestroy 注解。

2. 注解配置

2.1 注解

在讲基于注解配置之前,先看下之前的方式,新建一个项目

pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.cmz</groupId>
    <artifactId>spring_annotation_study</artifactId>
    <version>1.0-SNAPSHOT</version>

    <!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.2.3.RELEASE</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/junit/junit -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

</project>
PersonController.class
package com.cmz.controller;

import org.springframework.stereotype.Controller;

/**
 * @author summer
 * @create 2020-03-02 15:27
 */
public class PersonController {
}
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"
       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">
    <bean id="personController" class="com.cmz.controller.PersonController"></bean>
</beans>

MyTest.class

import com.cmz.controller.PersonController;
import com.cmz.service.PersonService;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * @author summer
 * @create 2020-03-02 15:53
 * 注意:
 *     1. 给测试类起名字的时候,千万不要定义成Test
 *     2. 测试的方法不可以有参数,也不可以有返回值
 */
public class MyTest {
    @Test
    public void test01(){
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        PersonController personController = context.getBean("personController", PersonController.class);
        System.out.println(personController);
    }
}

输出

com.cmz.controller.PersonController@6646153


接下来我们使用注解方式

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"
       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">
    <!--在之前的操作我们都是使用bean标签的方式向IOC容器中注册bean,
    下面使用注解的方式,当使用注册的时候,可以在当前类的上面添加某些注解标识
    @Component: 组件,理论上可以在任意的类上进行添加,在扫描的时候都会完成bean的注册
    @Controller: 放在控制层,用来接收用户的请求
    @service: 放在业务逻辑层
    @Repository: 放置在数据访问层

    这四个注解写在类上面的时候都可以完成注解的bean功能,但是这些规定并不是spring的是识别的标志,
    在spring程序运行过程中,不会对这四个注解做任何区分,看起来是一样的,都会完成bean的注册功能,
    在实际的开发过程中,最好能分清楚,提高代码的可读性。
    所以最偷懒的方式,就是给所有要注册的bean类上添加 @Component

    在使用注解的时候,还需要告诉spring应该从哪个包开始扫描.【需要导入context的命名空间】

    在使用注解的时候没有定义id和class,那么如何根据id来进行识别?
     默认是把当前类的名称的首字母小写作为id。如果想改变名称,需要再注解后面添加value值,一般没人改。
    -->
    <!--<bean id="personController" class="com.cmz.controller.PersonController"></bean>-->

    <context:component-scan base-package="com.cmz"></context:component-scan>
</beans>
PersonController.class
package com.cmz.controller;

import org.springframework.stereotype.Controller;

/**
 * @author summer
 * @create 2020-03-02 15:27
 */
@Controller
public class PersonController {
}

MyTest.class

import com.cmz.controller.PersonController;
import com.cmz.service.PersonService;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * @author summer
 * @create 2020-03-02 15:53
 * 注意:
 *     1. 给测试类起名字的时候,千万不要定义成Test
 *     2. 测试的方法不可以有参数,也不可以有返回值
 */
public class MyTest {
    @Test
    public void test01(){
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        PersonController personController = context.getBean("personController", PersonController.class);
        System.out.println(personController);
    }
}

输出结果一样。

com.cmz.controller.PersonController@6646153

2.2 匹配

在使用注解的生活没有定义id和class,那么如何根据id来进行识别?

  • 是把当前类的名称的首字母小写之后做识别的。
  • 也可以自定义

PersonController.class

package com.cmz.controller;

import org.springframework.stereotype.Controller;

/**
 * @author summer
 * @create 2020-03-02 15:27
 */
@Controller(value = "PC")
public class PersonController {
}

MyTest.class

import com.cmz.controller.PersonController;
import com.cmz.service.PersonService;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * @author summer
 * @create 2020-03-02 15:53
 * 注意:
 *     1. 给测试类起名字的时候,千万不要定义成Test
 *     2. 测试的方法不可以有参数,也不可以有返回值
 */
public class MyTest {
    @Test
    public void test01(){
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        PersonController personController = context.getBean("PC", PersonController.class);
        //PersonController personController = context.getBean("personController", PersonController.class);
        System.out.println(personController);
    }
}

输出

com.cmz.controller.PersonController@3b938003

其实就是在类的定义注解后面填入value值即可。不写,就是默认的,以类的首字母小写为标准。


单例

package com.cmz.controller;

import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Controller;

/**
 * @author summer
 * @create 2020-03-02 15:27
 */
@Controller
@Scope(value = "singleton")
public class PersonController {
}

多例

package com.cmz.controller;

import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Controller;

/**
 * @author summer
 * @create 2020-03-02 15:27
 */
@Controller
@Scope(value = "prototype")
public class PersonController {
}