java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > Java类配置与@Configuration

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

作者: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的作用

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实战内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文