Spring管理物件一般是通過注解@Component、xml(),如果我們不想通過spring,想自己操作讓spring無差別管理,那應該怎么做到呢?
我們知道Spring的Bean啟動順序大致是如下圖
分析:如果我們想不通過Spring的手段(@Component第),讓Spring管理我們的物件,我們可以通過在掃描的時候,將bean放到bd(BeanDefinition)中
幸運的是,Spring已經幫我們考慮到了這一點
Spring提供了一個后置處理器BeanDefinitionRegistryPostProcessor
public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor {
void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry var1) throws BeansException;
}
復制代碼
它的作用是在Spring開始根據BeanDefinition實體化之前,讓用戶通過介面引數BeanDefinitionRegistry做一些,最常見的處理就是通過BeanDefinitionRegistry.registerBeanDefinition注冊bd
以dubbo為例,我們知道,dubbo在使用注解@Service暴露介面的時候,會讓介面給到Spring管理,跟我們上面講的一致,
dubbo通過ServiceAnnotationBeanPostProcessor來實作這一功能
public class ServiceAnnotationBeanPostProcessor implements BeanDefinitionRegistryPostProcessor
復制代碼
spring啟動時,會進入它的post方法,一路debug進去到registerServiceBean
private void registerServiceBean(BeanDefinitionHolder beanDefinitionHolder, BeanDefinitionRegistry registry,DubboClassPathBeanDefinitionScanner scanner) {
Class<?> beanClass = resolveClass(beanDefinitionHolder);
Service service = findAnnotation(beanClass, Service.class);
Class<?> interfaceClass = resolveServiceInterfaceClass(beanClass, service);
String annotatedServiceBeanName = beanDefinitionHolder.getBeanName();
AbstractBeanDefinition serviceBeanDefinition =
buildServiceBeanDefinition(service, interfaceClass, annotatedServiceBeanName);
// ServiceBean Bean name
String beanName = generateServiceBeanName(service, interfaceClass, annotatedServiceBeanName);
//省略...........
}
復制代碼
重點方法 -> buildServiceBeanDefinition
private AbstractBeanDefinition buildServiceBeanDefinition(Service service, Class<?> interfaceClass,
String annotatedServiceBeanName) {
BeanDefinitionBuilder builder = rootBeanDefinition(ServiceBean.class);
AbstractBeanDefinition beanDefinition = builder.getBeanDefinition();
MutablePropertyValues propertyValues = beanDefinition.getPropertyValues();
String[] ignoreAttributeNames = of("provider", "monitor", "application", "module", "registry", "protocol",
"interface", "interfaceName");
propertyValues.addPropertyValues(new AnnotationPropertyValuesAdapter(service, environment, ignoreAttributeNames));
// References "ref" property to annotated-@Service Bean
addPropertyReference(builder, "ref", annotatedServiceBeanName);
// Set interface
builder.addPropertyValue("interface", interfaceClass.getName());
//從service獲取 對bd賦值
//省略...
return builder.getBeanDefinition();
}
復制代碼
利用ServiceBean作為類名生成BeanDefinition,并對其賦值,方便以后物件實體化生成相應的物件
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/213512.html
標籤:其他
