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 {@Beanpublic 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 {@Beandefault 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@Lazypublic 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@Primarypublic User user1() {return new User("anna");}@Beanpublic 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,否则会抛出异常