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 { }