注冊Spring Bean
XML配置元資訊
Java注解元資訊
- @Bean
- @Component及其派生注解
- @Import
Java接口繼承
ImportSelector
ImportBeanDefinitionRegistrar
Java API
注冊普通Bean
命名方式:
BeanDefinitionRegistry#registerBeanDefinition(String,BeanDefinition)
非命名方式:
BeanDefinitionReaderUtils#registerWithGeneratedName(AbstractBeanDefinition,Be anDefinitionRegistry)
void registerBeanDefinition(BeanDefinitionRegistry registry, AbstractBeanDefinition beanDefinition, String beanName) {
if (StringUtils.hasText(beanName)) {
// 注冊BeanDefinition
registry.registerBeanDefinition(beanName, beanDefinition);
} else {
// 注冊 非命名Bean
BeanDefinitionReaderUtils.registerWithGeneratedName(beanDefinition, registry);
// 按照 definitionHolder 注冊
// BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, registry);
}
}
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
applicationContext.refresh();
// 通過 AbstractBeanDefinition 以及派生類
AbstractBeanDefinition beanDefinition = new GenericBeanDefinition();
beanDefinition.setBeanClass(User.class);
MutablePropertyValues propertyValues = new MutablePropertyValues()
.add("id", 1)
.add("name", "wangrui");
// propertyValues.addPropertyValue("id", 1);
beanDefinition.setPropertyValues(propertyValues);
registerBeanDefinition(applicationContext, beanDefinition, "user");
registerBeanDefinition(applicationContext, beanDefinition, null);
Map<String, User> userMap = applicationContext.getBeansOfType(User.class);
// {user=User(id=1, name=wangrui), com.example.boot244.domain.model.User#0=User(id=1, name=wangrui)}
System.out.println(userMap);
注冊配置Bean
AnnotatedBeanDefinitionReader#register(Class...)
與AnnotatedBeanDefinitionReader一次隻注冊單個Bean相比,還有一個掃描器ClassPathBeanDefinitionScanner。但兩者差別在于:
AnnotatedBeanDefinitionReader:可以注冊任意類
ClassPathBeanDefinitionScanner:隻能掃描特定類
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
applicationContext.refresh();
AnnotatedBeanDefinitionReader reader = new AnnotatedBeanDefinitionReader(applicationContext);
reader.register(User.class);
User bean = applicationContext.getBean(User.class);
System.out.println(bean);
注冊單例Bean
SingletonBeanRegistry#registerSingleton
void test() throws Exception {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
applicationContext.refresh();
User user = new User().setId(1).setName("wangrui");
registerSingleton(applicationContext.getBeanFactory(), "user", user);
user = applicationContext.getBean(User.class);
System.out.println(user);
}
public void registerSingleton(SingletonBeanRegistry beanRegistry, String beanname, Object obj) {
beanRegistry.registerSingleton(beanname, obj);
}
執行個體化Bean
Bean正常方式
通過構造器(配置元資訊:XML、Java注解和Java API)
通過靜态方法(配置元資訊:XML和Java API)
通過執行個體方法(配置元資訊:XML和Java API)
通過FactoryBean(配置元資訊:XML、Java注解和Java API)
public class User {
private Integer id;
private String name;
// 靜态方法
public static User createUser() {
return new User().setId(1).setName("createUser");
}
}
public class UserFactory {
// 執行個體方法
public User createUser() {
return new User().setId(1).setName("factory工廠");
}
}
// 通過FactoryBean
public class UserFactoryBean implements FactoryBean<User> {
@Override
public User getObject() throws Exception {
return new User().setId(1).setName("userFactoryBean");
}
@Override
public Class<?> getObjectType() {
return User.class;
}
}
// 注冊工具
void registerBeanDefinition(BeanDefinitionRegistry registry, AbstractBeanDefinition beanDefinition, String beanName) {
if (StringUtils.hasText(beanName)) {
// 注冊BeanDefinition
registry.registerBeanDefinition(beanName, beanDefinition);
} else {
// 注冊 非命名Bean
BeanDefinitionReaderUtils.registerWithGeneratedName(beanDefinition, registry);
// 按照 definitionHolder 注冊
// BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, registry);
}
}
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
// UserFactoryBean屬于FactoryBean方式
applicationContext.register(UserFactory.class, UserFactoryBean.class);
applicationContext.refresh();
// 通過靜态工廠方法
AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition(User.class)
.setFactoryMethod("createUser")
.getBeanDefinition();
registerBeanDefinition(applicationContext, beanDefinition, null);
// 通過執行個體工廠方法
AbstractBeanDefinition beanDefinition1 = BeanDefinitionBuilder.genericBeanDefinition(User.class)
.setFactoryMethodOnBean("createUser", "userFactory")
.getBeanDefinition();
registerBeanDefinition(applicationContext, beanDefinition1, null);
Map<String, User> userMap = applicationContext.getBeansOfType(User.class);
System.out.println(userMap);
特殊方式
通過ServiceLoaderFactoryBean(配置元資訊:XML、Java注解和Java API)
public interface DemoFactory { }
public class DefaultDemoFactory implements DemoFactory { }
public class StandDemoFactory implements DemoFactory { }
META-INF/services/com.example.boot.service.DemoFactory
# 這裡用來展示去重
com.example.boot244.service.DefaultDemoFactory
com.example.boot244.service.StandDemoFactory
com.example.boot244.service.StandDemoFactory
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
applicationContext.refresh();
AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition(ServiceLoaderFactoryBean.class)
.addPropertyValue("serviceType", DemoFactory.class)
.getBeanDefinition();
registerBeanDefinition(applicationContext, beanDefinition, null);
ServiceLoader serviceLoader = applicationContext.getBean(ServiceLoader.class);
serviceLoader.forEach(System.out::println);
通過AutowireCapableBeanFactory#createBean
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
applicationContext.refresh();
// 此種方式可以觸發 依賴注入,但createBean(Class<T> beanClass)不能觸發依賴查找
User user = applicationContext.getBeanFactory().createBean(User.class);
System.out.println(user);
通過BeanDefinitionRegistry#registerBeanDefinition
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
applicationContext.refresh();
AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition(User.class)
.addPropertyValue("id", 1)
.addPropertyValue("name", "wangrui")
.getBeanDefinition();
applicationContext.registerBeanDefinition("user", beanDefinition);
User user = applicationContext.getBean(User.class);
System.out.println(user);
Bean初始化
@PostConstruct
實作InitializingBean接口
自定義初始化方法
XML配置:
Java注解:@Bean(initMethod="")
Java API:AbstractBeanDefinition#setInitMethodName
那以上三種方式均在同一Bean中定義,那麼這些方法的執行順序是怎樣的呢?
- @PostConstruct
- 實作InitializingBean接口
- 自定義初始化方法
public class Person implements InitializingBean {
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("InitializingBean#afterPropertiesSet() : 初始化中...");
}
@PostConstruct
public void init() {
System.out.println("@PostConstruct : 初始化中...");
}
public void initFactory() {
System.out.println("自定義初始化方法 initUserFactory() : 初始化中...");
}
}
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
applicationContext.refresh();
AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition(Person.class)
.setInitMethodName("initFactory")
.getBeanDefinition();
BeanDefinitionReaderUtils.registerWithGeneratedName(beanDefinition, applicationContext);
Person person = applicationContext.getBean(Person.class);
Bean銷毀
@PreDestory
實作DisposableBean接口
自定義銷毀方法
XML配置:
Java注解:@Bean(destory="")
Java API:AbstractBeanDefinition#setDestroyMethodName
那以上三種方式均在同一Bean中定義,那麼這些方法的執行順序是怎樣的呢?
- @PreDestory
- 實作DisposableBean接口
- 自定義銷毀方法
public class Person implements DisposableBean {
@Override
public void destroy() throws Exception {
System.out.println("DisposableBean#destroy() : 銷毀中...");
}
@PreDestroy
public void destory() {
System.out.println("@PreDestroy : 銷毀中...");
}
public void destoryFactory() {
System.out.println("自定義銷毀方法 doDestroy() : 銷毀中...");
}
}
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
applicationContext.refresh();
AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition(Person.class)
.setDestroyMethodName("destoryFactory")
.getBeanDefinition();
BeanDefinitionReaderUtils.registerWithGeneratedName(beanDefinition, applicationContext);
Person person = applicationContext.getBean(Person.class);
System.out.println(person);
applicationContext.close();