Spring(3)-手動註冊BeanDefinition
大體思路:
1、選擇BeanDefinition的實現類,並例項化BeanDefinition
2、註冊BeanDefinition
3、獲取Bean,看看是不是正常工作的。
非抽象的實現類主要有三個
1、GenericBeanDefinition,這個也是官方推薦使用的,註釋裡提到可以動態設定parentbeandefinition等。
2、RootBeanDefinition,這個跟@Configuration註解有關。
3、ChildBeanDefinition,這個也可以實現設定parentbeandefinition,不過它是預先定義parent/child關係,官方也不推薦使用了,看註釋可以知道,從spring2.5開始
GenericBeanDefinition已經替代ChildBeanDefinition了。
基於以上思路,我們選擇GenericBeanDefinition
public class GenericBeanDefinition extends AbstractBeanDefinition { @Nullable private String parentName; /** * Create a new GenericBeanDefinition, to be configured through its bean * properties and configuration methods. *@see #setBeanClass * @see #setScope * @see #setConstructorArgumentValues * @see #setPropertyValues */ public GenericBeanDefinition() { super(); } /** * Create a new GenericBeanDefinition as deep copy of the given * bean definition. * @param original the original bean definition to copy from*/ public GenericBeanDefinition(BeanDefinition original) { super(original); } @Override public void setParentName(@Nullable String parentName) { this.parentName = parentName; } @Override @Nullable public String getParentName() { return this.parentName; } @Override public AbstractBeanDefinition cloneBeanDefinition() { return new GenericBeanDefinition(this); } @Override public boolean equals(@Nullable Object other) { if (this == other) { return true; } if (!(other instanceof GenericBeanDefinition)) { return false; } GenericBeanDefinition that = (GenericBeanDefinition) other; return (ObjectUtils.nullSafeEquals(this.parentName, that.parentName) && super.equals(other)); } @Override public String toString() { if (this.parentName != null) { return "Generic bean with parent '" + this.parentName + "': " + super.toString(); } return "Generic bean: " + super.toString(); } }
框架裡面一般是怎麼使用GenericBeanDefinition的呢?
一般是在BeanDefinitionBuilder裡面,或者是BeanDefinitionReaderUtils,我記得是這個,由於這個筆記本不好用,簡單搜下
然後就是註冊BeanDefinition了
找一個beanFactory,
public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {
不只實現了ConfigurableListableBeanFactory,還實現了BeanDefinitionRegistry
public interface BeanDefinitionRegistry extends AliasRegistry { /** * Register a new bean definition with this registry. * Must support RootBeanDefinition and ChildBeanDefinition. * @param beanName the name of the bean instance to register * @param beanDefinition definition of the bean instance to register * @throws BeanDefinitionStoreException if the BeanDefinition is invalid * @throws BeanDefinitionOverrideException if there is already a BeanDefinition * for the specified bean name and we are not allowed to override it * @see GenericBeanDefinition * @see RootBeanDefinition * @see ChildBeanDefinition */ void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws BeanDefinitionStoreException; .......... }
所以,我們只要呼叫這個beanFactory的註冊方法即可。
生成beanName
BeanNameGenerator介面,有兩個實現類
public interface BeanNameGenerator { /** * Generate a bean name for the given bean definition. * @param definition the bean definition to generate a name for * @param registry the bean definition registry that the given definition * is supposed to be registered with * @return the generated bean name */ String generateBeanName(BeanDefinition definition, BeanDefinitionRegistry registry); }
AnnatationBeanNameGenerator就是我們平時使用的註解方式@Autowired,的一個這樣的格式,而預設的beanName則是,類名稱+#+0(com.spring.learn.service.impl.TestServiceImpl#0)這樣的。
bean之間的依賴
通過constructor,或者property方式注入
之前不是說過BeanDefinition接口裡面有兩個引數,一個是關於建構函式,一個是關於屬性set方法注入的。
構造器注入程式碼
GenericBeanDefinition controllerBeanDefinition = (GenericBeanDefinition) BeanDefinitionBuilder. genericBeanDefinition(TestControllerWithConstructor.class) .addConstructorArgValue("controller name is TestController") .addConstructorArgReference(testServiceName) .getBeanDefinition();
屬性值注入程式碼
GenericBeanDefinition propertyControllerBeanDefinition = (GenericBeanDefinition) BeanDefinitionBuilder .genericBeanDefinition(TestControllerWithProperty.class) .addPropertyValue("name","name is property controller") .addPropertyReference("testService",testServiceName).getBeanDefinition();
完成注入程式碼:
public static void main(String[] args) { // SpringApplication.run(SpringLearnApplication.class, args); //建立一個工廠來 DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory(); //建立beanDefinition GenericBeanDefinition beanDefinition = (GenericBeanDefinition) BeanDefinitionBuilder.genericBeanDefinition(TestServiceImpl.class) .getBeanDefinition(); //建立beanDefinition Name String testServiceName = AnnotationBeanNameGenerator.INSTANCE.generateBeanName(beanDefinition,beanFactory); //注入到spring 工廠裡 beanFactory.registerBeanDefinition(testServiceName,beanDefinition); //建立controller,這個builder模式裡邊,要呼叫constructor的方法 GenericBeanDefinition controllerBeanDefinition = (GenericBeanDefinition) BeanDefinitionBuilder. genericBeanDefinition(TestControllerWithConstructor.class) .addConstructorArgValue("controller name is TestController") .addConstructorArgReference(testServiceName) .getBeanDefinition(); String controllerBeanName = AnnotationBeanNameGenerator.INSTANCE.generateBeanName(controllerBeanDefinition,beanFactory); beanFactory.registerBeanDefinition(controllerBeanName,controllerBeanDefinition); //--------------------------------------------- //注入之後,再取出來,將controller裡面service和 spring裡面的service作對比是不是一樣的。 TestControllerWithConstructor testController = (TestControllerWithConstructor) beanFactory.getBean(controllerBeanName); TestService testService = (TestService) beanFactory.getBean(testServiceName); Assert.isTrue(testController.getTestService()==testService,"他們不相等,有問題"); //__________________________________________________ //這個是通過屬性值property注入到DefaultListableBeanFactory GenericBeanDefinition propertyControllerBeanDefinition = (GenericBeanDefinition) BeanDefinitionBuilder .genericBeanDefinition(TestControllerWithProperty.class) .addPropertyValue("name","name is property controller") .addPropertyReference("testService",testServiceName).getBeanDefinition(); String propertyControllerName = AnnotationBeanNameGenerator.INSTANCE.generateBeanName(propertyControllerBeanDefinition,beanFactory); beanFactory.registerBeanDefinition(propertyControllerName,propertyControllerBeanDefinition); //注入進去之後,再取出propertyController TestControllerWithProperty propertyController = (TestControllerWithProperty) beanFactory.getBean(propertyControllerName); System.out.println(propertyController.getName()); Assert.isTrue(propertyController.getTestService()==testService,"他們不相等,有問題"); }
https://www.cnblogs.com/grey-wolf/p/12070377.html
今天就到這了,我去看別的了,