纯Java类配置与@Configuration实战指南
作者:tlnshuju
前言
在前几篇博客中,我们从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组合配置类
假设有两个配置类MyConfig
和MyConfig1
:
// 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实战内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!