Spring之@Bean注解

1. 使用方式

1.1 @Configuration + @Bean

1.1.1 创建实体类 User
复制代码
@Data
@NoArgsConstructor
public class User {

    private String name;

    public User(String name) {
        this.name = name;
    }
}
1.1.2 创建配置类 UserConfig
复制代码
@Configuration
public class UserConfig {

    @Bean
    public User user() {
        return new User("anna");
    }
}
1.1.3 创建配置类 AppConfig
复制代码
@ComponentScan("com.ys")
public class AppConfig {
}
1.1.4 创建启动类 Main
复制代码
public class Main {

    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
    }
}
1.1.5 运行 main 方法,查看运行结果

通过运行结果,得出结论:Spring 容器中存在类型为 User 的 bean

1.2 接口默认方法

1.2.1 创建实体类 DefaultCar、RedCar 以及接口 Car
复制代码
public class DefaultCar implements Car {
}

@Component
public class RedCar implements Car {
}

public interface Car {

    @Bean
    default DefaultCar defaultCar() {
        return new DefaultCar();
    }
}
1.2.1 运行 main 方法,查看运行结果

通过运行结果,得出结论:Spring 容器中存在类型为 DefaultCar 的 bean

1.3 其他

  • @Bean 标注的方法既可以是实例方法也可以是静态方法
  • 除了 @Configuration + @Bean 的组合使用,原则上 @Component + @Bean、@ManagedBean + @Bean 也是可以的,主要是 full 和 lite 的区别,相关博文:Spring之什么是配置类

2. @Bean 各属性作用

2.1 name、value

指定 beanName ,未指定则为方法名

2.1.1 修改 UserConfig
复制代码
@Configuration
public class UserConfig {

    @Bean("anna")
    public User user() {
        return new User("anna");
    }
}
2.1.2 运行 main 方法,查看运行结果

通过运行结果,得出结论:如果指定了 name,则就不存在 beanName 为 user(方法名) 的 bean

2.2 autowire

注入模型(已过期)

2.2.1 修改实体类 User
复制代码
@Data
@NoArgsConstructor
public class User {

    private String name;

    private RedCar redCar;

    public User(String name) {
        this.name = name;
    }

}
2.2.2 修改 UserConfig
复制代码
@Configuration
public class UserConfig {

    @Bean(name = "anna", autowire = Autowire.BY_TYPE)
    public User user() {
        return new User("anna");
    }
}
2.2.3 运行 main 方法,查看运行结果

通过运行结果,得出结论:User 有个内部属性 redCar**,如果注入模式是** byType**,即使没有** @Autowired****注解,也会自动注入进去

相关知识点:Spring之注入模型

2.3 autowireCandidate

当注入的依赖存在多个候选者,如果候选者的 autowireCandidate 属性为 false,则不加入候选

2.3.1 修改 UserConfig
复制代码
@Configuration
public class UserConfig {

    @Bean(name = "anna", autowireCandidate = false)
    public User user1() {
        return new User("anna");
    }

    @Bean(name = "bob")
    public User user2() {
        return new User("bob");
    }
}
2.3.2 运行 main 方法,查看运行结果

通过运行结果,得出结论:Spring 容器中一共有两个类型的为 User 的 bean,默认情况下,context.getBean(User.class) 如果找到多个 bean 会抛出异常,但是其中一个 bean 相关的 BeanDefinition 的 autowireCandidate 属性为 false,则表示它不是一个候选者,因此不会抛出异常,只返回 name 为 bob 的 bean

2.4 initMethod、destroyMethod

2.4.1 给实体类 User 添加相关方法
复制代码
@Data
@NoArgsConstructor
public class User {

    private String name;

    private RedCar redCar;

    public User(String name) {
        this.name = name;
    }

    public void userInit() {
        System.out.println("user init");
    }

    public void userDestroy() {
        System.out.println("user destroy");
    }
}
2.4.2 修改 UserConfig
复制代码
@Configuration
public class UserConfig {

    @Bean(initMethod = "userInit", destroyMethod = "userDestroy")
    public User user() {
        return new User("anna");
    }

}
2.4.3 运行 main 方法,查看运行结果

通过运行结果,得出结论:相应方法会在特定的生命周期执行

3. @Bean和其他注解搭配使用

3.1 @Lazy

3.1.1 修改 UserConfig
复制代码
@Configuration
public class UserConfig {

    @Bean
    @Lazy
    public User user() {
        return new User("anna");
    }

}
3.1.2 运行 main 方法,查看运行结果

通过运行结果,得出结论:在 getBean 方法执行之前一共有 17 个 bean,方法执行之后有 18 个bean,即相关 bean 是懒加载的

3.2 @Primary

3.2.1 修改 UserConfig
复制代码
@Configuration
public class UserConfig {

    @Bean
    @Primary
    public User user1() {
        return new User("anna");
    }

    @Bean
    public User user2() {
        return new User("bob");
    }

}
3.2.2 运行 main 方法,查看运行结果

通过运行结果,得出结论:@Primary 注解和其 autowireCandidate 属性的功能类似,都是选择最优候选者

3.3 @DependsOn

3.3.1 修改 UserConfig
复制代码
@Configuration
public class UserConfig {

    @Bean
    @DependsOn("user2")
    public User user1() {
        return new User("anna");
    }

//    @Bean
//    public User user2() {
//        return new User("bob");
//    }

}
3.3.2 运行 main 方法,查看运行结果

通过运行结果,得出结论:Spring 容器中必须存在指定 names 的 bean,否则会抛出异常

相关推荐
majingming1237 小时前
FUNCTION
java·前端·javascript
zopple7 小时前
常见的 Spring 项目目录结构
java·后端·spring
xuxie999 小时前
N11 ARM-irq
java·开发语言
cjy0001119 小时前
springboot的 nacos 配置获取不到导致启动失败及日志不输出问题
java·spring boot·后端
wefly20179 小时前
从使用到原理,深度解析m3u8live.cn—— 基于 HLS.js 的 M3U8 在线播放器实现
java·开发语言·前端·javascript·ecmascript·php·m3u8
zhenxin01229 小时前
Spring Boot实现定时任务
java
小江的记录本10 小时前
【事务】Spring Framework核心——事务管理:ACID特性、隔离级别、传播行为、@Transactional底层原理、失效场景
java·数据库·分布式·后端·sql·spring·面试
sheji341610 小时前
【开题答辩全过程】以 基于springboot的校园失物招领系统为例,包含答辩的问题和答案
java·spring boot·后端
寂静or沉默10 小时前
2026最新Java岗位从P5-P7的成长面试进阶资源分享!
java·开发语言·面试
卓怡学长10 小时前
m289在线交友系统
java·spring·tomcat·maven·intellij-idea·hibernate