Spring(3)-手动注册BeanDefinition
大体思路:
1、选择BeanDefinition的实现类,并实例化BeanDefinition
2、注册BeanDefinition
3、获取Bean,看看是不是正常工作的。
非抽象的实现类主要有三个
1、GenericBeanDefinition,这个也是官方推荐使用的,注释里提到可以动态设置parent bean definition等。
2、RootBeanDefinition,这个跟@Configuration注解有关。
3、ChildBeanDefinition,这个也可以实现设置parent bean definition,不过它是预先定义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
今天就到这了,我去看别的了,