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,否则会抛出异常

相关推荐
葫芦和十三1 小时前
图解 MongoDB 21|选举与 failover:Primary 是怎么选出来的
后端·mongodb·agent
GetcharZp2 小时前
26k Star 开源内网穿透神器 NetBird,一分钟实现全球设备互联!
后端
考虑考虑3 小时前
Mybatis实现批量插入
java·后端·mybatis
咖啡八杯3 小时前
GoF设计模式——中介者模式
java·后端·spring·设计模式
lizhongxuan6 小时前
多Agent之间的区别
后端
青石路7 小时前
记一次多JDK版本问题的排查,一坑套一坑,差点没爬上来
java
杨充8 小时前
1.面向对象设计思想
后端
IT_陈寒8 小时前
Java的Date类又坑了我一次,改用时间戳真香
前端·人工智能·后端
systemPro8 小时前
2.6亿条设备数据,历史查询从超时到50ms,我做了什么
后端
要阿尔卑斯吗9 小时前
提示词优化启示:为什么“按顺序输出“比“关键度评分“更有效
后端