欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Spring注解驱动开发第2讲——使用@Configuration和@Bean给容器中注册组件

程序员文章站 2024-03-19 16:33:28
...

写在前面

在以前学习Spring的过程中,我们是通过编写XML配置文件来定义我们的Bean的,这种编写XML配置文件的方式不仅繁琐,而且还很容易出错,稍有不慎就会导致编写的应用程序各种报错,排查半天,发现是XML文件配置不对!另外,每个项目都编写大量的XML文件来配置Spring,也大大增加了项目维护的复杂度,往往很多个项目的Spring XML文件的配置大部分是相同的,只有很少量的配置不同,这也造成了配置文件上的冗余。

而要是使用了Spring注解驱动来开发,你会发现以上这些问题都将不存在了。整个世界都变得清静了,于是你不由得会心一笑????!这也导致了学习Spring注解驱动开发是一件多么迫不急待地事,正如教员说的那句话:

多少事,从来急。天地转,光阴迫。一万年太久,只争朝夕!

我喜欢教员!毛选第一卷还看了一大部分。我还非常喜欢国际歌,特别喜欢第六段:

是谁创造了人类世界?
是我们劳动群众!
一切归劳动者所有,
哪能容得寄生虫?
最可恨那些毒蛇猛兽,
吃尽了我们的血肉!
一旦把它们消灭干净,
鲜红的太阳照遍全球!

鲜红的太阳必将照遍全球!!!

Spring IOC和DI

在Spring容器的底层,最重要的功能就是IOC和DI,也就是控制反转和依赖注入。
Spring注解驱动开发第2讲——使用@Configuration和@Bean给容器中注册组件
DI和IOC它俩之间的关系是DI不能单独存在,DI需要在IOC的基础上来完成。

在Spring内部,所有的组件都会放到IOC容器中,组件之间的关系通过IOC容器来自动装配,也就是我们所说的依赖注入。接下来,我们就使用注解的方式来完成容器中组件的注册、管理及依赖、注入等功能。

在介绍使用注解完成容器中组件的注册、管理及依赖、注入等功能之前,我们先来看看使用XML配置文件是如何注入Bean的。

通过XML配置文件注入JavaBean

首先,新建一个maven项目,例如spring-annotation-liayun,注意其打包方式是jar。
Spring注解驱动开发第2讲——使用@Configuration和@Bean给容器中注册组件
这个时候我们发现新建的maven项目的编译版本是1.5。那这还玩个毛啊!要知道现在都2020年末了,都快出Java 16这个版本了,但为了稳定,公司里面现在普遍使用的都是Java 8,所以在这里我们需要设置编译版本为1.8,即在pom文件中添加maven插件指定编译时候使用的JDK版本。

<build>
    <plugins>
        <!-- java编译插件 -->
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.5.1</version>
            <configuration>
                <source>1.8</source>
                <target>1.8</target>
                <encoding>UTF-8</encoding>
            </configuration>
        </plugin>
    </plugins>
</build>

以上只是调整局部JDK版本。这时,你会发现新建的maven项目依然会报错,如下图所示。
Spring注解驱动开发第2讲——使用@Configuration和@Bean给容器中注册组件
这个报错你也不用担心,因为有时候加依赖或者插件,maven项目就会报错。这时,就需要时不时地Update一下项目了,Update项目之后,你就会发现项目的编译版本为1.8了,如下图所示。
Spring注解驱动开发第2讲——使用@Configuration和@Bean给容器中注册组件
然后,在pom文件中添加对Spring的依赖,注意咱们在这儿使用的Spring是4.3.12.RELEASE这个版本的。

<dependencies>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>4.3.12.RELEASE</version>
    </dependency>
</dependencies>

接着,在工程的com.meimeixia.bean包下创建一个Person类,作为测试的JavaBean,代码如下所示。

package com.meimeixia.bean;

public class Person {
	
	private String name;
	private Integer age;
	
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public Integer getAge() {
		return age;
	}
	public void setAge(Integer age) {
		this.age = age;
	}
	public Person(String name, Integer age) {
		super();
		this.name = name;
		this.age = age;
	}
	public Person() {
		super();
		// TODO Auto-generated constructor stub
	}
	@Override
	public String toString() {
		return "Person [name=" + name + ", age=" + age + "]";
	}
	
}

紧接着,在工程的src/main/resources目录下创建Spring的配置文件,例如beans.xml,通过该配置文件将Person类注入到Spring的IOC容器中,该配置文件中的内容如下所示。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p"
	xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
	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-4.2.xsd">
	
	<!-- 注册组件 -->
	<bean id="person" class="com.meimeixia.bean.Person">
		<property name="age" value="18"></property>
		<property name="name" value="liayun"></property>
	</bean>
	
</beans>

至此,我们使用XML配置文件的方式注入JavaBean就完成了。

接下来,我们在工程的com.meimeixia包下创建一个MainTest类来进行测试,该类的代码如下所示。

package com.meimeixia;

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

import com.meimeixia.bean.Person;

public class MainTest {

	public static void main(String[] args) {
		ApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");
		Person person = (Person) applicationContext.getBean("person");
		System.out.println(person);
	}
	
}

运行以上main方法,输出的结果信息如下图所示。
Spring注解驱动开发第2讲——使用@Configuration和@Bean给容器中注册组件
从输出结果中,我们可以看出,Person类通过beans.xml文件的配置,已经注入到Spring的IOC容器中去了。

通过注解注入JavaBean

通过XML配置文件的方式,我们可以将JavaBean注入到Spring的IOC容器中。那使用注解又该如何实现呢?别急,其实使用注解比使用XML配置文件要简单的多,我们在项目的com.meimeixia.config包下创建一个MainConfig类,并在该类上添加@Configuration注解来标注该类是一个Spring的配置类,也就是告诉Spring它是一个配置类,最后通过@Bean注解将Person类注入到Spring的IOC容器中。

package com.meimeixia.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import com.meimeixia.bean.Person;
/**
 * 以前配置文件的方式被替换成了配置类,即配置类==配置文件
 * @author liayun
 *
 */
// 这个配置类也是一个组件 
@Configuration // 告诉Spring这是一个配置类
public class MainConfig {

	// @Bean注解是给IOC容器中注册一个Bean,类型自然就是返回值的类型,id默认是用方法名作为id
	@Bean
	public Person person() {
		return new Person("liayun", 20);
	}
	
}

没错,通过MainConfig类我们就能够将Person类注入到Spring的IOC容器中,是不是很Nice啊!!主要是我们在类上加上@Configuration注解,并在方法上加上@Bean注解,就能够将方法中创建的JavaBean注入到Spring的IOC容器中。

然后,我们修改MainTest类中的main方法,以测试通过注解注入的Person类,如下所示。

package com.meimeixia;

import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.meimeixia.bean.Person;
import com.meimeixia.config.MainConfig;

public class MainTest {

	public static void main(String[] args) {
//		ApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");
//		Person person = (Person) applicationContext.getBean("person");
//		System.out.println(person);
		
		ApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);
		Person person = applicationContext.getBean(Person.class);
		System.out.println(person);
	}
	
}

再次运行以上main方法,输出的结果信息如下图所示。
Spring注解驱动开发第2讲——使用@Configuration和@Bean给容器中注册组件
可以看出,通过注解将Person类注入到了Spring的IOC容器中。

到这里,我们已经明确了,通过XML配置文件和注解这两种方式都可以将JavaBean注入到Spring的IOC容器中。那么,使用注解将JavaBean注入到IOC容器中时,使用的bean的名称又是什么呢?我们可以在MainTest类的main方法中添加如下代码来获取Person这个类型的组件在IOC容器中的名字。

// Person这个类型的组件在IOC容器中的名字是什么呢?
String[] namesForType = applicationContext.getBeanNamesForType(Person.class);
for (String name : namesForType) {
    System.out.println(name);
}

这样,MainTest类的main方法的完整代码如下所示。

package com.meimeixia;

import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.meimeixia.bean.Person;
import com.meimeixia.config.MainConfig;

public class MainTest {

	public static void main(String[] args) {
//		ApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");
//		Person person = (Person) applicationContext.getBean("person");
//		System.out.println(person);
		
		ApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);
		Person person = applicationContext.getBean(Person.class);
		System.out.println(person);
		
		// Person这个类型的组件在IOC容器中的名字是什么呢?
		String[] namesForType = applicationContext.getBeanNamesForType(Person.class);
		for (String name : namesForType) {
			System.out.println(name);
		}
	}
	
}

运行以上main方法之后,输出的结果信息如下图所示。
Spring注解驱动开发第2讲——使用@Configuration和@Bean给容器中注册组件
那这里打印出的person到底是啥呢?我们修改下MainConfig类中的person()方法,将其名字修改成person01,如下所示。

package com.meimeixia.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import com.meimeixia.bean.Person;
/**
 * 以前配置文件的方式被替换成了配置类,即配置类==配置文件
 * @author liayun
 *
 */
// 这个配置类也是一个组件 
@Configuration // 告诉Spring这是一个配置类
public class MainConfig {

	// @Bean注解是给IOC容器中注册一个Bean,类型自然就是返回值的类型,id默认是用方法名作为id
	@Bean
	public Person person01() {
		return new Person("liayun", 20);
	}
	
}

此时,我们再次运行MainTest类中的main方法,输出的结果信息如下图所示。
Spring注解驱动开发第2讲——使用@Configuration和@Bean给容器中注册组件
看到这里,大家应该有种豁然开朗的感觉了,没错!!使用注解注入JavaBean时,Bean在IOC容器中的名称就是使用@Bean注解标注的方法名称。我们可不可以为Bean单独指定名称呢?那必须可以啊!只要在@Bean注解中明确指定名称就可以了。比如在下面MainConfig类的代码中,我们将person01()方法上的@Bean注解修改成了@Bean(“person”)注解,如下所示。

package com.meimeixia.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import com.meimeixia.bean.Person;
/**
 * 以前配置文件的方式被替换成了配置类,即配置类==配置文件
 * @author liayun
 *
 */
// 这个配置类也是一个组件 
@Configuration // 告诉Spring这是一个配置类
public class MainConfig {

	// @Bean注解是给IOC容器中注册一个Bean,类型自然就是返回值的类型,id默认是用方法名作为id
	@Bean("person")
	public Person person01() {
		return new Person("liayun", 20);
	}
	
}

此时,我们再次运行MainTest类中的main方法,输出的结果信息如下图所示。
Spring注解驱动开发第2讲——使用@Configuration和@Bean给容器中注册组件
可以看到,此时,输出的JavaBean的名称确实是person了。

小结

我们在使用注解方式向Spring的IOC容器中注入JavaBean时,如果没有在@Bean注解中明确指定Bean的名称,那么就会使用当前方法的名称来作为Bean的名称;如果在@Bean注解中明确指定了Bean的名称,那么就会使用@Bean注解中指定的名称来作为Bean的名称。