文章目录
先看下看看注解@Configuration
的定义。
package org.springframework.context.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.core.annotation.AliasFor;
import org.springframework.stereotype.Component;
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Configuration {
@AliasFor(
annotation = Component.class
)
String value() default "";
boolean proxyBeanMethods() default true;
}
其中,proxyBeanMethods
,字面意思是“代理Bean的方法”。布尔值,是否代理Bean的方法,默认是true,即@Configuration
等同于@Configuration(proxyBeanMethods=true)
。
proxyBeanMethods
为true时,- Full模式,即全量模式。
- 每次调用@Bean方法返回的组件都是单实例。
每次调用@Bean方法时,SpringBoot都会检查容器中是否存在组件 ,如果存在,则返回单实例;如果不存在,则创建单实例。 - 适用于 组件依赖 的场景。
proxyBeanMethods
为false时,- Lite模式,即轻量模式。
- 每次调用@Bean方法返回的组件都是新创建的。
每次调用@Bean方法时,SpringBoot不用检查容器中是否存在组件,直接返回一个新创建的实例。 - 组件间没有依赖 的场景。因为跳过了组件检查,所以SpringBoot的启动、加载都会快一些。
@Configuration 或 @Configuration(proxyBeanMethods = true)
注解@Configuration标注在类上,告诉SpringBoot该类是一个配置类。配置类本身是一个组件,在配置类中使用@Bean标注在方法上为容器注册组件,被标注的方法返回的实例默认是单实例。
看个例子就明白了。
- 新建Maven工程:demo。
- 修改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>com.example</groupId>
<artifactId>demo</artifactId>
<version>1.0-SNAPSHOT</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.6.1</version>
</parent>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.12</version>
<scope>provided</scope>
</dependency>
</dependencies>
</project>
- 在java下新建包com.example.boot.bean,在bean下新建类:User和Pet。
package com.example.boot.bean;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@NoArgsConstructor
@AllArgsConstructor
@Data
public class User {
private String name;
private Integer age;
}
package com.example.boot.bean;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@NoArgsConstructor
@AllArgsConstructor
@Data
public class Pet {
private String name;
}
- 新建包com.example.boot.config,config下新建配置类MyConfig。
package com.example.boot.config;
import com.example.boot.bean.Pet;
import com.example.boot.bean.User;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class MyConfig {
@Bean
public User user01(){
return new User("zhangsan",18);
}
@Bean
public Pet pet01(){
return new Pet("tomcat");
}
}
- com.example.boot下新建主程序类MainApplication。
package com.example.boot;
import com.example.boot.bean.User;
import com.example.boot.config.MyConfig;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
@SpringBootApplication
public class MainApplication {
public static void main(String[] args) {
ConfigurableApplicationContext ctx = SpringApplication.run(MainApplication.class,args);
//配置类本身是一个组件
MyConfig myConfig = ctx.getBean(MyConfig.class);
//配置类中使用@Bean注册的组件,无论调用多少次,返回的组件都是单实例
User user01 = myConfig.user01();
User user02 = myConfig.user01();
System.out.println("user01 == user02, 返回"+ (user01 == user02));
}
}
- 启动程序,查看控制台打印的信息,如下。
@Configuration(proxyBeanMethods = false)
- proxyBeanMethods为false时,每次调用被@Bean标注的方法,返回的实例都是新创建的。
不妨将MyConfig中的@Configuration修改为@Configuration(proxyBeanMethods = false),然后重新启动应用程序试试。
package com.example.boot.config;
import com.example.boot.bean.Pet;
import com.example.boot.bean.User;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration(proxyBeanMethods = false)
public class MyConfig {
@Bean
public User user01(){
return new User("zhangsan",18);
}
@Bean
public Pet pet01(){
return new Pet("tomcat");
}
}
- 注册组件之间存在依赖的场景:User类中有个Pet类型的属性pet。
package com.example.boot.bean;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@NoArgsConstructor
@AllArgsConstructor
@Data
public class User {
private String name;
private Integer age;
private Pet pet;
public User(String name,Integer age){
new User(name,age,null);
}
}
package com.example.boot.bean;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@NoArgsConstructor
@AllArgsConstructor
@Data
public class Pet {
private String name;
}
package com.example.boot.config;
import com.example.boot.bean.Pet;
import com.example.boot.bean.User;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration(proxyBeanMethods = true)
public class MyConfig {
@Bean
public User user01(){
User zs = new User("zhangsan",18);
zs.setPet(pet01());
return zs;
}
@Bean
public Pet pet01(){
return new Pet("tomcat");
}
}
package com.example.boot;
import com.example.boot.bean.User;
import com.example.boot.config.MyConfig;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
@SpringBootApplication
public class MainApplication {
public static void main(String[] args) {
ConfigurableApplicationContext ctx = SpringApplication.run(MainApplication.class,args);
MyConfig myConfig = ctx.getBean(MyConfig.class);
User user01 = myConfig.user01();
System.out.println(user01.getPet().getName());
}
}
启动应用,控制台打印出如下信息:“tomcat”。