1. 程式人生 > 實用技巧 >不用@Component怎麼讓spring管理你的物件?

不用@Component怎麼讓spring管理你的物件?

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,並對其賦值,方便以後物件例項化生成相應的物件