【Spring注解开发】使用@Configuration和@Bean向容器中注册组件?看这一篇就够了!!

简介: 在之前的Spring版本中,我们只能通过写XML配置文件来定义我们的Bean,XML配置不仅繁琐,而且很容易出错,稍有不慎就会导致编写的应用程序各种报错,排查半天,发现是XML文件配置不对!另外,每个项目编写大量的XML文件来配置Spring,也大大增加了项目维护的复杂度,往往很多个项目的Spring XML文件的配置大部分是相同的,只有很少量的配置不同,这也造成了配置文件上的冗余。项目工程源码已经提交到GitHub:https://github.com/sunshinelyz/spring-annotation

Spring IOC和DI

在Spring容器的底层,最重要的功能就是IOC和DI,也就是控制反转和依赖注入。

IOC:控制反转,将类的对象的创建交给Spring类管理创建。

DI:依赖注入,将类里面的属性在创建类的过程中给属性赋值。

DI和IOC的关系:DI不能单独存在,DI需要在IOC的基础上来完成。

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

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

通过XML文件注入JavaBean

首先,我们在工程的io.mykit.spring.bean包下创建Person类,作为测试的JavaBean,代码如下所示。

package io.mykit.spring.bean;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;
import java.io.Serializable;
/**
 * @author binghe
 * @version 1.0.0
 * @description 测试实体类
 */
@Data
@ToString
@NoArgsConstructor
@AllArgsConstructor
public class Person implements Serializable {
    private static final long serialVersionUID = 7387479910468805194L;
    private String name;
    private Integer age;
}

接下来,我们在工程的resources目录下创建Spring的配置文件beans.xml,通过beans.xml文件将Person类注入到Spring的IOC容器中,配置如下所示。

<?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 id = "person" class="io.mykit.spring.bean.Person">
        <property name="name" value="binghe"></property>
        <property name="age" value="18"></property>
    </bean>
</beans>

到此,我们使用XML方式注入JavaBean就配置完成了。接下来,我们创建一个SpringBeanTest类来进行测试,这里,我使用的是Junit进行测试,测试方法如下所示。

@Test
public void testXmlConfig(){
    ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
    Person person = (Person) context.getBean("person");
    System.out.println(person);
}

运行testXmlConfig()方法,输出的结果信息如下。

Person(name=binghe, age=18)

从输出结果中,我们可以看出,Person类通过beans.xml文件的配置,已经注入到Spring的IOC容器中了。

通过注解注入JavaBean

通过XML文件,我们可以将JavaBean注入到Spring的IOC容器中。那使用注解又该如何实现呢?别急,其实使用注解比使用XML文件要简单的多,我们在项目的io.mykit.spring.plugins.register.config包下创建PersonConfig类,并在PersonConfig类上添加@Configuration注解来标注PersonConfig类是一个Spring的配置类,通过@Bean注解将Person类注入到Spring的IOC容器中。

package io.mykit.spring.plugins.register.config;
import io.mykit.spring.bean.Person;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
 * @author binghe
 * @version 1.0.0
 * @description 以注解的形式来配置Person
 */
@Configuration
public class PersonConfig {
     @Bean
    public Person person(){
        return new Person("binghe001", 18);
    }
}

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

接下来,我们在SpringBeanTest类中创建一个testAnnotationConfig()方法来测试通过注解注入的Person类,如下所示。

@Test
public void testAnnotationConfig(){
    ApplicationContext context = new AnnotationConfigApplicationContext(PersonConfig.class);
    Person person = context.getBean(Person.class);
    System.out.println(person);
}

运行testAnnotationConfig()方法,输出的结果信息如下所示。

Person(name=binghe001, age=18)

可以看出,通过注解将Person类注入到了Spring的IOC容器中。

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

//按照类型找到对应的bean名称数组
String[] names = context.getBeanNamesForType(Person.class);
Arrays.stream(names).forEach(System.out::println);

完整的testAnnotationConfig()方法的代码如下所示。

@Test
public void testAnnotationConfig(){
    ApplicationContext context = new AnnotationConfigApplicationContext(PersonConfig.class);
    Person person = context.getBean(Person.class);
    System.out.println(person);
    //按照类型找到对应的bean名称数组
    String[] names = context.getBeanNamesForType(Person.class);
    Arrays.stream(names).forEach(System.out::println);
}

运行testAnnotationConfig()方法输出的结果信息如下所示。

Person(name=binghe001, age=18)
person

那这里的person是啥?我们修改下PersonConfig类中的person()方法,将person()方法修改成person01()方法,如下所示。

package io.mykit.spring.plugins.register.config;
import io.mykit.spring.bean.Person;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
 * @author binghe
 * @version 1.0.0
 * @description 以注解的形式来配置Person
 */
@Configuration
public class PersonConfig {
    @Bean
    public Person person01(){
        return new Person("binghe001", 18);
    }
}

此时,我们再次运行testAnnotationConfig()方法,输出的结果信息如下所示。

Person(name=binghe001, age=18)
person01

看到这里,大家应该有种豁然开朗的感觉了,没错!!使用注解注入Javabean时,bean在IOC中的名称就是使用@Bean注解标注的方法名称。我们可不可以为bean单独指定名称呢?那必须可以啊!只要在@Bean注解中明确指定名称就可以了。比如下面的PersonConfig类的代码,我们将person01()方法上的@Bean注解修改成@Bean("person")注解,如下所示。

package io.mykit.spring.plugins.register.config;
import io.mykit.spring.bean.Person;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
 * @author binghe
 * @version 1.0.0
 * @description 以注解的形式来配置Person
 */
@Configuration
public class PersonConfig {
    @Bean("person")
    public Person person01(){
        return new Person("binghe001", 18);
    }
}

此时,我们再次运行testAnnotationConfig()方法,输出的结果信息如下所示。

Person(name=binghe001, age=18)
person

可以看到,此时,输出的JavaBean的名称为person。

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

相关文章
|
7月前
|
XML Java 应用服务中间件
【SpringBoot(一)】Spring的认知、容器功能讲解与自动装配原理的入门,带你熟悉Springboot中基本的注解使用
SpringBoot专栏开篇第一章,讲述认识SpringBoot、Bean容器功能的讲解、自动装配原理的入门,还有其他常用的Springboot注解!如果想要了解SpringBoot,那么就进来看看吧!
725 2
|
存储 Java 数据库
Spring Boot 注册登录系统:问题总结与优化实践
在Spring Boot开发中,注册登录模块常面临数据库设计、密码加密、权限配置及用户体验等问题。本文以便利店销售系统为例,详细解析四大类问题:数据库字段约束(如默认值缺失)、密码加密(明文存储风险)、Spring Security配置(路径权限不当)以及表单交互(数据丢失与提示不足)。通过优化数据库结构、引入BCrypt加密、完善安全配置和改进用户交互,提供了一套全面的解决方案,助力开发者构建更 robust 的系统。
444 0
|
XML Java 测试技术
Spring5入门到实战------17、Spring5新功能 --Nullable注解和函数式注册对象。整合JUnit5单元测试框架
这篇文章介绍了Spring5框架的三个新特性:支持@Nullable注解以明确方法返回、参数和属性值可以为空;引入函数式风格的GenericApplicationContext进行对象注册和管理;以及如何整合JUnit5进行单元测试,同时讨论了JUnit4与JUnit5的整合方法,并提出了关于配置文件加载的疑问。
Spring5入门到实战------17、Spring5新功能 --Nullable注解和函数式注册对象。整合JUnit5单元测试框架
|
XML Java 数据格式
Spring5入门到实战------7、IOC容器-Bean管理XML方式(外部属性文件)
这篇文章是Spring5框架的实战教程,主要介绍了如何在Spring的IOC容器中通过XML配置方式使用外部属性文件来管理Bean,特别是数据库连接池的配置。文章详细讲解了创建属性文件、引入属性文件到Spring配置、以及如何使用属性占位符来引用属性文件中的值。
Spring5入门到实战------7、IOC容器-Bean管理XML方式(外部属性文件)
|
XML Java 数据格式
Spring5入门到实战------6、IOC容器-Bean管理XML方式(自动装配)
这篇文章是Spring5框架的入门教程,详细讲解了IOC容器中Bean的自动装配机制,包括手动装配、`byName`和`byType`两种自动装配方式,并通过XML配置文件和Java代码示例展示了如何在Spring中实现自动装配。
Spring5入门到实战------6、IOC容器-Bean管理XML方式(自动装配)
|
XML 缓存 Java
spring源码剖析-spring-beans(内部核心组件,BeanDefinition的注册,BeanWapper创建)
spring源码剖析-spring-beans(内部核心组件,BeanDefinition的注册,BeanWapper创建)
281 10
|
存储 Java 程序员
SpringIOC和DI的代码实现,Spring如何存取对象?@Controller、@Service、@Repository、@Component、@Configuration、@Bean DI详解
本文详细讲解了Spring框架中IOC容器如何存储和取出Bean对象,包括五大类注解(@Controller、@Service、@Repository、@Component、@Configuration)和方法注解@Bean的用法,以及DI(依赖注入)的三种注入方式:属性注入、构造方法注入和Setter注入,并分析了它们的优缺点。
415 0
SpringIOC和DI的代码实现,Spring如何存取对象?@Controller、@Service、@Repository、@Component、@Configuration、@Bean DI详解
|
前端开发 Java Docker
使用Docker容器化部署Spring Boot应用程序
使用Docker容器化部署Spring Boot应用程序
|
Java Docker 微服务
利用Docker容器化部署Spring Boot应用
利用Docker容器化部署Spring Boot应用
375 0
|
XML Java 数据格式
Spring5入门到实战------8、IOC容器-Bean管理注解方式
这篇文章详细介绍了Spring5框架中使用注解进行Bean管理的方法,包括创建Bean的注解、自动装配和属性注入的注解,以及如何用配置类替代XML配置文件实现完全注解开发。
Spring5入门到实战------8、IOC容器-Bean管理注解方式