作用
在Spring Boot中,@Configuration注解是一个非常重要的组件
@Configuration注解在类上,将该类设置为springboot的配置类,相当于springmvc中的xml文件。配置类本身也是一个组件和容器。
被注解的类内部包含有一个或多个被@Bean注解的方法,这些方法将会被扫描,并用于构建bean定义,初始化Spring容器。
proxyBeanMethods :
存在组件依赖时,属性值应该为true,不存在组件依赖时,可以用false。
编码实现
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>springboot-learning</artifactId>
<version>1.0-SNAPSHOT</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.7.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-core</artifactId>
</dependency>
<!-- <dependency>-->
<!-- <groupId>org.mybatis.spring.boot</groupId>-->
<!-- <artifactId>mybatis-spring-boot-starter</artifactId>-->
<!-- <version>2.1.3</version>-->
<!-- </dependency>-->
<!-- <dependency>-->
<!-- <groupId>mysql</groupId>-->
<!-- <artifactId>mysql-connector-java</artifactId>-->
<!-- <version>8.0.25</version>-->
<!-- <scope>runtime</scope>-->
<!-- </dependency>-->
<!-- <dependency>-->
<!-- <groupId>org.springframework.boot</groupId>-->
<!-- <artifactId>spring-boot-starter-test</artifactId>-->
<!-- <scope>test</scope>-->
<!-- </dependency>-->
<!-- <dependency>-->
<!-- <groupId>junit</groupId>-->
<!-- <artifactId>junit</artifactId>-->
<!-- <version>4.12</version>-->
<!-- <scope>test</scope>-->
<!-- </dependency>-->
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
将MyConfig.java设置为Springboot的配置类:
1.配置类里面使用@Bean标注在方法上,给容器注册组件,默认也是单实例的
2.配置类本身也是组件
3.proxyBeanMethods: 代理bean的方法
Full(proxyBeanMethods = true) 默认,调用多次方法,只产生一个对象
Lite(proxyBeanMethods = false) 每次调用这些方法,都会产生一个新的对象
给容器中自动创建出这两个类型的组件,组件名字默认是全类名
MyConfig.java
package com.zwy.boot.config;
import ch.qos.logback.core.db.DBHelper;
import com.zwy.boot.bean.Pet;
import com.zwy.boot.bean.User;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
/**
* 1.配置类里面使用@Bean标注在方法上,给容器注册组件,默认也是单实例的
* 2.配置类本身也是组件
* 3.proxyBeanMethods: 代理bean的方法
* Full(proxyBeanMethods = true) 默认,调用多次方法,只产生一个对象
* Lite(proxyBeanMethods = false) 每次调用这些方法,都会产生一个新的对象
* 给容器中自动创建出这两个类型的组件,组件名字默认是全类名
* @author zwy
*/
@Configuration(proxyBeanMethods = true)
public class MyConfig {
/**
* 外部无论对配置类中这个组件注册方法调用多少次,获取的都是之前注册容器中的单实例对象
* @return User
*/
@Bean
public User user01() {
User zhangsan = new User("zhangsan", 18);
// User组件依赖了Pet组件
zhangsan.setPet(tomcatPet());
return zhangsan;
}
@Bean
public Pet tomcatPet() {
return new Pet("tomcat");
}
}
其中启动类有:
MainApplication.java
package com.zwy.boot;
import ch.qos.logback.core.db.DBHelper;
import com.zwy.boot.bean.Pet;
import com.zwy.boot.bean.User;
import com.zwy.boot.config.MyConfig;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
/**
* 主程序类; 主配置类
* 注解@SpringBootApplication:这是一个springboot应用
* @author zwy
*/
@SpringBootApplication
public class MainApplication {
public static void main(String[] args) {
// 1.返回IOC容器
ConfigurableApplicationContext run = SpringApplication.run(MainApplication.class, args);
// 2.查看容器里面的组件
String[] names = run.getBeanDefinitionNames();
for (String name : names) {
System.out.println(name);
}
System.out.println("======================");
// 3.从容器中获取组件,注册
Pet pet1 = run.getBean("tom", Pet.class);
Pet pet2 = run.getBean("tom", Pet.class);
System.out.println("组件:" + (pet1 == pet2));
MyConfig bean = run.getBean(MyConfig.class);
System.out.println(bean);
User user1 = bean.user01();
User user2 = bean.user01();
System.out.println(user1 == user2);
// 4.验证proxyBeanMethods=false时,用户的宠物是不是容器中的宠物?
User user01 = run.getBean("user01", User.class);
Pet tom = run.getBean("tom", Pet.class);
System.out.println("用户的宠物:" + (user01.getPet() == tom));
}
}
另外有:
User.java
package com.zwy.boot.bean;
/**
* 用户
* @author zwy
*/
public class User {
private String name;
private Integer age;
private Pet pet;
public User() {
}
public User(String name, Integer age) {
this.name = name;
this.age = 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 Pet getPet() {
return pet;
}
public void setPet(Pet pet) {
this.pet = pet;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", age=" + age +
", pet=" + pet +
'}';
}
}
Pet.java
package com.zwy.boot.bean;
/**
* 宠物
* @author zwy
*/
public class Pet {
private String name;
public Pet() {
}
public Pet(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Pet{" +
"name='" + name + '\'' +
'}';
}
}
文件结构
有文件结构如下:
运行
如果proxyBeanMethods = false,每次调用这些方法,都会产生一个新的对象,此时用户的宠物就不是宠物了,会显示用户的宠物:false
总结
@Configuration注解总结:
- 声明配置类:当你在类级别上使用@Configuration注解时,你告诉Spring Boot这个类包含了一些配置信息和Bean的定义。
- 定义Bean:
在配置类中,你可以使用@Bean注解在一个方法上,表示该方法会返回一个对象,这个对象应该被注册为Spring容器中的Bean。这意味着当你需要这个Bean的时候,Spring会调用这个方法来获取它。 - 替代XML配置:
在传统的Spring应用中,通常使用XML文件来配置Bean和应用程序上下文。然而,在Spring Boot中,@Configuration注解的类可以作为一个替代方案,允许你在Java代码中进行配置,而不是在XML文件中。 - 代理Bean方法:
@Configuration注解有一个可选的属性proxyBeanMethods,默认值为true。如果设置为true,Spring会为配置类生成CGLIB代理,确保在同一个配置类中@Bean方法之间的相互调用也会经过Spring容器的生命周期管理。如果设置为false,则不会生成代理,这可以提高性能,但需要注意@Bean方法间的依赖关系可能无法正确处理。 - 导入其他配置类:
你可以使用@Import注解来导入其他的@Configuration类,这样就可以将多个配置类组合在一起,形成一个完整的配置环境。 - 声明环境属性:
虽然不常见,但在某些情况下,@Configuration类也可以用来声明环境属性,这些属性可以在应用程序中通过@Value注解或者其他方式使用。 - 作用域:
默认情况下,通过@Bean注解创建的Bean是单例的。如果你需要改变Bean的作用域,可以使用@Scope注解。 - 与@Component的关系:
@Configuration注解的类同时也是@Component注解的一个特例,因此它们会被Spring的组件扫描机制自动检测到并加入到应用程序上下文中。
总的来说,@Configuration注解在Spring Boot中扮演着核心的角色,它允许开发者以类型安全、更直观的方式在Java代码中进行应用程序的配置和Bean的定义,而不是依赖于XML配置文件。这种方式使得配置更加灵活,易于理解和维护。
参考
https://blog.csdn.net/gaochenglong1/article/details/107387284
https://www.cnblogs.com/Infinity-Finish/articles/15759136.html