不用@Component怎麼讓spring管理你的物件?
阿新 • • 發佈:2020-11-13
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,並對其賦值,方便以後物件例項化生成相應的物件