纯Java类配置与@Configuration实战指南

 更新时间:2025年09月18日 08:59:20   作者:tlnshuju  
本文介绍@Configuration的核心用法,实战@Bean定义Bean、@ComponentScan扫描组件、@Import组合配置类,带大家体验“无XML”的Spring配置新方式,感兴趣的朋友跟随小编一起看看吧

前言

在前几篇博客中,我们从XML配置逐步过渡到注解驱动开发,掌握了@Component@Autowired等核心注解。但注解仍需依赖少量XML(如<context:component-scan>),有没有办法彻底摆脱XML,让所有配置都“写在Java类里”?

答案就是Spring的纯Java类配置(Java-based Configuration)。通过@Configuration注解,我们可以把原本写在XML里的配置(如组件扫描、Bean定义)全部转移到Java类中,让配置与业务代码更紧密地结合。

本文将聚焦@Configuration的核心用法,实战@Bean定义Bean、@ComponentScan扫描组件、@Import组合配置类,带大家体验“无XML”的Spring配置新方式。

一、纯Java类配置的核心:@Configuration

@Configuration是Spring纯Java配置的“入口注解”,被它标记的类会被Spring视为配置类(相当于XML配置文件),类中可以定义Bean、指定组件扫描规则等。

1.1 @Configuration的作用

  • 替代XML配置文件,让配置“代码化”;
  • 配置类本身也会被Spring管理,作为一个Bean存在于容器中;
  • 支持通过@Bean@ComponentScan等注解,在类中完成所有Spring配置。

1.2 实战:创建第一个配置类

我们先写一个最简单的配置类,感受它如何替代XML:

package com.niit.config;
import org.springframework.context.annotation.Configuration;
// @Configuration:标记当前类为Spring的配置类,相当于beans.xml
@Configuration
public class MyConfig
{
// 这里暂时为空,后续添加Bean定义和扫描规则
}

二、手动定义@Bean

@Bean是配置类中定义Bean的核心注解,作用相当于XML中的<bean>标签。被@Bean标记的方法,其返回值会被Spring注册为Bean,方法名默认作为Bean的id

2.1 基本用法

假设我们有一个Student类,需要将其注册为Bean:

package com.niit.pojo;
public class Student
{
private String name = "默认学生";
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
'}';
}
}

在配置类中,用@Bean定义这个Student的Bean:

package com.niit.config;
import com.niit.pojo.Student;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class MyConfig
{
// @Bean:将方法返回的Student对象注册为Spring的Bean,id默认为方法名“getStudent”
@Bean
public Student getStudent() {
return new Student();
}
}

2.2 测试@Bean定义的Bean

通过AnnotationConfigApplicationContext加载配置类,获取Bean:

import com.niit.config.MyConfig;
import com.niit.pojo.Student;
import org.junit.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class MyTest
{
@Test
public void testBean() {
// 加载配置类(替代ClassPathXmlApplicationContext加载XML)
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MyConfig.class)
;
// 获取Bean,id为方法名“getStudent”
Student student = context.getBean("getStudent", Student.class)
;
System.out.println(student);
// 输出:Student{name='默认学生'}
context.close();
}
}

2.3 自定义Bean的id

如果不想用方法名作为Bean的id,可以给@Bean指定name属性:

@Bean(name = "myStudent")
public Student getStudent() {
return new Student();
}

测试时,通过新的id获取:

Student student = context.getBean("myStudent", Student.class)
;

三、@ComponentScan

@ComponentScan的作用和XML中的<context:component-scan>一致,用于指定Spring要扫描的包,自动注册带有@Component@Service@Repository等注解的类为Bean。

3.1 基本用法

假设com.niit.pojo包下有一个带@Component的类:

package com.niit.pojo;
import org.springframework.stereotype.Component;
@Component
public class Teacher
{
private String name = "张老师";
@Override
public String toString() {
return "Teacher{" +
"name='" + name + '\'' +
'}';
}
}

在配置类中添加@ComponentScan,指定扫描com.niit.pojo包:

package com.niit.config;
import com.niit.pojo.Student;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
// 扫描com.niit.pojo包下的组件
@ComponentScan(basePackages = {
"com.niit.pojo"
})
public class MyConfig
{
@Bean
public Student getStudent() {
return new Student();
}
}

3.2 测试组件扫描

加载配置类后,不仅能获取@Bean定义的Student,还能获取扫描到的Teacher

@Test
public void testComponentScan() {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MyConfig.class)
;
// 获取@Bean定义的Student
Student student = context.getBean("getStudent", Student.class)
;
System.out.println(student);
// 获取扫描到的Teacher(id为类名首字母小写“teacher”)
Teacher teacher = context.getBean("teacher", Teacher.class)
;
System.out.println(teacher);
// 输出:Teacher{name='张老师'}
context.close();
}

3.3 @ComponentScans:组合多个扫描规则

如果需要同时扫描多个包或配置复杂的扫描规则,可以用@ComponentScans组合多个@ComponentScan

@Configuration
@ComponentScans({
@ComponentScan(basePackages = "com.niit.pojo"),
@ComponentScan(basePackages = "com.niit.service")
})
public class MyConfig
{
// ...
}

四、@Import:组合多个配置类

当配置类较多时,可通过@Import将多个配置类合并,统一加载。

4.1 实战:用@Import组合配置类

假设有两个配置类MyConfigMyConfig1

// MyConfig.java
package com.niit.config;
import com.niit.pojo.Student;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan(basePackages = {
"com.niit.pojo"
})
public class MyConfig
{
@Bean
public Student getStudent() {
return new Student();
}
}
// MyConfig1.java
package com.niit.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
@Configuration
@Import(MyConfig.class)
// 导入MyConfig配置类
public class MyConfig1
{
// 可添加自己的Bean定义或扫描规则
}

4.2 测试@Import

只需加载MyConfig1,即可同时包含MyConfig的配置:

@Test
public void testImport() {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MyConfig1.class)
;
// 能获取MyConfig中定义的Student
Student student = context.getBean("getStudent", Student.class)
;
System.out.println(student);
// 能获取MyConfig扫描到的Teacher
Teacher teacher = context.getBean("teacher", Teacher.class)
;
System.out.println(teacher);
context.close();
}

五、完整代码结构与测试

5.1 代码结构

com.niit
├─ config
│  ├─ MyConfig.java
│  └─ MyConfig1.java
├─ pojo
│  ├─ Student.java
│  └─ Teacher.java
└─ test
└─ MyTest.java

5.2 各文件代码

MyConfig.java

package com.niit.config;
import com.niit.pojo.Student;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan(basePackages = {
"com.niit.pojo"
})
public class MyConfig
{
@Bean
public Student getStudent() {
return new Student();
}
}

MyConfig1.java

package com.niit.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
@Configuration
@Import(MyConfig.class)
public class MyConfig1
{
}

Student.java

package com.niit.pojo;
public class Student
{
private String name = "默认学生";
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
'}';
}
}

Teacher.java

package com.niit.pojo;
import org.springframework.stereotype.Component;
@Component
public class Teacher
{
private String name = "张老师";
@Override
public String toString() {
return "Teacher{" +
"name='" + name + '\'' +
'}';
}
}

MyTest.java

import com.niit.config.MyConfig;
import com.niit.config.MyConfig1;
import com.niit.pojo.Student;
import com.niit.pojo.Teacher;
import org.junit.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class MyTest
{
@Test
public void test() {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MyConfig.class)
;
Student student = context.getBean("getStudent", Student.class)
;
System.out.println(student);
Teacher teacher = context.getBean("teacher", Teacher.class)
;
System.out.println(teacher);
context.close();
}
@Test
public void testImport() {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MyConfig1.class)
;
Student student = context.getBean("getStudent", Student.class)
;
System.out.println(student);
Teacher teacher = context.getBean("teacher", Teacher.class)
;
System.out.println(teacher);
context.close();
}
}

到此这篇关于纯Java类配备与@Configuration实战的文章就介绍到这了,更多相关纯Java类配备与@Configuration实战内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 解决IDEA2020.1版本不兼容Lombok的问题

    解决IDEA2020.1版本不兼容Lombok的问题

    这篇文章主要介绍了解决IDEA2020.1版本不兼容Lombok的问题,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-04-04
  • jdk中String类设计成final的原由

    jdk中String类设计成final的原由

    为什么jdk中把 String 类设计成final,主要是为了“ 效率 ”和“安全性”的缘故,若 String 允许被继承, 由于它的高度被使用率, 可能会降低程序的性能,所以String被定义成final,需要了解的朋友可以参考下
    2013-01-01
  • Spring Data Jpa多表查询返回自定义实体方式

    Spring Data Jpa多表查询返回自定义实体方式

    这篇文章主要介绍了Spring Data Jpa多表查询返回自定义实体方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-02-02
  • SpringBoot Redis用注释实现接口限流详解

    SpringBoot Redis用注释实现接口限流详解

    Redis 除了做缓存,还能干很多很多事情:分布式锁、限流、处理请求接口幂等性。。。太多太多了~今天想和小伙伴们聊聊用 Redis 处理接口限流,这也是最近的 项目涉及到这个知识点了,我就拎出来和大家聊聊这个话题
    2022-07-07
  • SpringCloud-Nacos服务注册与发现方式

    SpringCloud-Nacos服务注册与发现方式

    这篇文章主要介绍了SpringCloud-Nacos服务注册与发现方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-07-07
  • 使用Spring Boot上传文件功能

    使用Spring Boot上传文件功能

    上传文件是互联网中常应用的场景之一,最典型的情况就是上传头像等,今天就带着大家做一个Spring Boot上传文件的小案例,感兴趣的朋友跟随脚本之家小编一起学习吧
    2018-01-01
  • java 中动态代理(JDK,cglib)实例代码

    java 中动态代理(JDK,cglib)实例代码

    这篇文章主要介绍了java 中动态代理,这里介绍了JDK 动态代理与 cglib 动态代理的相关资料
    2017-04-04
  • 详解spring面向切面aop拦截器

    详解spring面向切面aop拦截器

    spring中有很多概念和名词,比如过滤器、拦截器、aop等。这篇文章主要介绍了详解spring面向切面aop拦截器,有兴趣的可以了解一下。
    2017-03-03
  • Spring集成MyBatis框架

    Spring集成MyBatis框架

    本文主要介绍了Spring集成MyBatis的配置和使用,项目基于Maven构建,连接Mysql数据库。下面跟着小编一起来看下吧
    2017-02-02
  • Java判断时间段内文件是否更新的方法

    Java判断时间段内文件是否更新的方法

    这篇文章主要介绍了Java判断时间段内文件是否更新的方法,通过实例形式讲述了定时器、类加载器及线程等方法实现判断文件更新的功能,具有一定的参考借鉴价值,需要的朋友可以参考下
    2014-12-12

最新评论