Spring的BeanDefinitionRegistryPostProcessor使用

BeanDefinitionRegistryPostProcessor就是用來自定義bean的,並手動注入到Spring的容器裏面,有時候覺得定義bean直接使用註解或者xml配置更方便,但是Spring既然提供,肯定是有道理,嘗試一下。

這種使用一般是自己用來封裝一些擴展插件的時候使用。

BeanDefinitionRegistryPostProcessor 就是一個定義很簡單的接口,要想實現實現自定義bean只需要實現這個接口就行。

/**
 * Extension to the standard {@link BeanFactoryPostProcessor} SPI, allowing for
 * the registration of further bean definitions <i>before</i> regular
 * BeanFactoryPostProcessor detection kicks in. In particular,
 * BeanDefinitionRegistryPostProcessor may register further bean definitions
 * which in turn define BeanFactoryPostProcessor instances.
 *
 * @author Juergen Hoeller
 * @since 3.0.1
 * @see org.springframework.context.annotation.ConfigurationClassPostProcessor
 */
public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor {

	/**
	 * Modify the application context's internal bean definition registry after its
	 * standard initialization. All regular bean definitions will have been loaded,
	 * but no beans will have been instantiated yet. This allows for adding further
	 * bean definitions before the next post-processing phase kicks in.
	 * @param registry the bean definition registry used by the application context
	 * @throws org.springframework.beans.BeansException in case of errors
	 */
	void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException;

}

自定義實現bean定義

package com.madman.annotation.springextension;

import com.madman.annotation.entity.Blue;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;

/**
 * <pre>
 * 【類型】: CustomBeanDefinitionRegistryPostProcessor <br/>
 * 【作用】: 請填寫此類的作用<br/>
 * 【時間】:2019/1/3 14:50 <br/>
 * 【作者】:madman <br/>
 * </pre>
 */
@Configuration
@Component
public class CustomBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {
    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
        BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.rootBeanDefinition("com.madman.annotation.entity.Blue");
        beanDefinitionBuilder.addPropertyValue("name", "小鵬一號");
        beanDefinitionBuilder.addPropertyValue("age", "18");

        BeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition(Blue.class).getBeanDefinition();
        beanDefinition.getPropertyValues().add("name", "小鵬二號");
        beanDefinition.getPropertyValues().add("age", "28");


        registry.registerBeanDefinition("bule_01", beanDefinitionBuilder.getBeanDefinition());
        registry.registerBeanDefinition("bule_02", beanDefinition);

    }

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {

    }
}

自定義bean最重要的類就是BeanDefinition接口了,這個接口裏面定義了註冊bean的各種屬性,一般我們定義bean的時候都是用的BeanDefinitionBuilder這個spring提供的定義bean的工具類,上面的這個自定義的bean裏面也是用的這個來創建bean。
上面的代碼使用了兩種形式創建了bean,

這種形式是直接通過類名的全路徑進行定義的,定義好之後可以addPropertyValue方法來設置屬性。
        BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.rootBeanDefinition("com.madman.annotation.entity.Blue");
beanDefinitionBuilder.addPropertyValue("name", "小鵬一號");
這種形式就是通過Class的形式來定義bean的,這個形式得到的是BeanDefinition對象,所以設置屬性的方式和上面不一樣。
        BeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition(Blue.class).getBeanDefinition();
beanDefinition.getPropertyValues().add("name", "小鵬二號");
最後註冊bean使用的是registry的registerBeanDefinition方法來註冊bean,registry屬性也有很多方法,是否包含,移除bean等操作,可以用來判斷bean是否存在或者名字是否存在等一些操作。
        registry.registerBeanDefinition("bule_02", beanDefinition);

自定義bean之後,就需要使用這類注入到spring容器裏面去,這裏我直接使用了@Configuration,@Component這兩個註解,把這類當成一個組件,掃描的時候直接掃進去就行了。
最後測試的結果是這樣的,屬性和上面是一一對應的。

public class start_1 {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext annotation = new AnnotationConfigApplicationContext(Config_1.class);
        Map<String, Blue> beansOfType = annotation.getBeansOfType(Blue.class);
        for (String s : beansOfType.keySet()) {
            System.out.println("名字是:" + s);
            System.out.println(beansOfType.get(s).toString());
        }
    }
}
無參數構造函數
無參數構造函數
無參數構造函數
名字是:blue
Blue{name='19', age=12}
名字是:bule_01
Blue{name='小鵬一號', age=18}
名字是:bule_02
Blue{name='小鵬二號', age=28}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章