使用注解创建bean
@Configuration表示这是一个配置类,在方法上加@Bean注解表示这个方法返回的对象是一个bean,
如果不指定@Bean的value值,这个bean的name默认是方法名
@Configuration
public class BeanConfig {
@Bean("user1")
public User user() {
return new User("月清疏", 18);
}
}
接下来打印bean的名字看看
第一步,获取applicationContext对象
@Component
public class ApplicationContextUtil implements ApplicationContextAware {
private static ApplicationContext context;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
context = applicationContext;
}
public static ApplicationContext getApplicationContext() {
return context;
}
}
第二步,写个测试类打印
@RunWith(SpringRunner.class)
@SpringBootTest
@Slf4j
public class BeanTest {
@Test
public void testBean() {
String[] names = ApplicationContextUtil.getApplicationContext().getBeanNamesForType(User.class);
Arrays.stream(names).forEach(log::info);
}
}
可以看到打印了指定的名字user1
2021-10-29 16:32:43.197 com.wkt.beantest.BeanTest : user1
@Scope
bean默认都是单例的,可以通过Scope注解来控制生成多实例,通过传prototype,则每次bean被注入或者获取,user方法都会被调用并且生成一个新的对象
/**
* prototype: 多实例
* singleton: 单实例,默认值
*
* @return
*/
@Scope("prototype")
@Bean
public User user() {
System.out.println("创建了user实例");
return new User("月清疏", 18);
}
@Lazy
懒加载,默认bean都是容器一启动就加载了,加了这个注解后bean只有在使用的时候才会去加载
@Import
import注解在SpringBoot中很重要,因为自动配置里面导入bean就用到了这个注解。
import注解有三种用法,先来看一个最简单的用法
@Configuration
@Import(Color.class)
public class BeanConfig {
这种方法就是注册一个bean,跟@Bean一样,唯一的不同是这个bean的name是全路径包名+类名。
第二种是最常见的用法,通过ImportSelector接口来注册。这种注册方式的好处是通过类名就能注册bean了,而类名可以通过配置文件读入。
public class MyImportSelector implements ImportSelector {
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
return new String[]{"com.wkt.config.Color"};
}
}
@Configuration
@Import(MyImportSelector.class)
public class BeanConfig {
第三种是第二种的升级版,它可以让你指定bean的name.
public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
RootBeanDefinition root = new RootBeanDefinition(Color.class);
registry.registerBeanDefinition("color", root);
}
}
@Configuration
@Import(MyImportBeanDefinitionRegistrar.class)
public class BeanConfig {
@Resource和@Autowired
@Autowired默认按类型装配,默认情况下必须要求依赖对象必须存在,如果要允许null值,可以设置它的required属性为false。
@Resource默认按名称装配,当找不到与名称匹配的bean时才按照类型进行装配。名称可以通过name属性指定,如果没有指定name属性,当注解写在字段上时,默认取字段名,当注解写在setter方法上时,默认取属性名进行装配。
@Primary
如果同一类型注册了好几个bean,那用按类型装配如Autowired的就会报错,因为它不知道用哪个bean,这时就可以在一个bean上面加Primary注解来明确指定
@Bean
@Primary
public Color red() {
return new Color("红色");
}
@Bean
public Color blue() {
return new Color("蓝色");
}
@DependsOn
控制bean的注册顺序,下面的代码表示color组件要user组件注册完才会去注册
@Data
@AllArgsConstructor
@DependsOn({"user"})
@Component
public class Color {
private String color;
}