BeanDefinition
顾名思义就是 Bean的定义, 那么他应该包含Bean的元信息. 所以就是这个意思. 对的他就是这么个意思.
Spring中对于BeanFactory生成的Bean全部由这个去定义的.
我们看看Spring提供了什么的BeanDefinition
基本就是上图所示的几种. 大部分都是由 abs组成的. 另一个是内部类. 我们不考虑 ,
那么我们就学学如何使用吧.
GenericBeanDefinition
它是个通用的.
public class SringApp { @Data static class Bean { String name; int age; } public static void main(String[] args) { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); GenericBeanDefinition definition = new GenericBeanDefinition(); definition.setBeanClass(Bean.class); definition.getPropertyValues().add("name", "xiaoli"); definition.getPropertyValues().add("age", 1); // 注册. context.registerBeanDefinition("bean1", definition); context.refresh(); Bean bean = (Bean) context.getBean("bean1"); System.out.println(bean); } } 复制代码
其实还可以继承的
public static void main(String[] args) { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); GenericBeanDefinition definition = new GenericBeanDefinition(); definition.setBeanClass(Bean.class); definition.getPropertyValues().add("name", "xiaoli"); definition.getPropertyValues().add("age", 1); context.registerBeanDefinition("bean1", definition); GenericBeanDefinition definition2 = new GenericBeanDefinition(); definition2.setParentName("bean1"); // bean2 的属性继承了 bean1 context.registerBeanDefinition("bean2", definition2); context.refresh(); Bean bean1 = (Bean) context.getBean("bean1"); Bean bean2 = (Bean) context.getBean("bean2"); // 虽然是这样,但是返回的false. 因为只是继承了属性. System.out.println(bean1==bean2); } 复制代码
那么它何时加载的. 显然是在 context.refresh();
的时候. 在fresh中的这个方法中. 初始化non-lazy.
// Instantiate all remaining (non-lazy-init) singletons. finishBeanFactoryInitialization(beanFactory); // 然后进入在 // Instantiate all remaining (non-lazy-init) singletons. beanFactory.preInstantiateSingletons(); // 主要流程就是去注册Bean. 到 , 详细代码可以看看. 其实很简单的. 复制代码
RootBeanDefinition
和 ChildBeanDefinition
这俩成双成对的. 你说不是吗. root节点不能有父类 , 其中儿子节点, 必须有父类 . 用法上和上面那个没啥区别.
public static void main(String[] args) { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); // root RootBeanDefinition definition = new RootBeanDefinition(); definition.setBeanClass(Bean.class); definition.getPropertyValues().add("name", "xiaoli"); definition.getPropertyValues().add("age", 1); context.registerBeanDefinition("bean1", definition); // child ChildBeanDefinition definition2 = new ChildBeanDefinition("bean1"); context.registerBeanDefinition("bean2", definition2); // 刷新 context.refresh(); Bean bean1 = (Bean) context.getBean("bean1"); Bean bean2 = (Bean) context.getBean("bean2"); System.out.println(bean1==bean2); } 复制代码
BeanDefinitionBuilder
工具 很显然就是一个Builder的工具类.
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(Bean.class); // lazy 的意思是. 你需要(调用get("beanname")方法)的时候才要实例化. builder.setLazyInit(true); // builder.getBeanDefinition() 其实是一个 GenericBeanDefinition context.registerBeanDefinition("bean3", builder.getBeanDefinition()); 复制代码
BeanDefinitionHolder
类 很显然是一个持有者
// 三个参数: // beanDefinition , bean_name, bean_alias(别名的意思就是小名,可以通过小名获取) BeanDefinitionHolder holder = new BeanDefinitionHolder(definition, "bean1", new String[]{"bean2"}); context.registerBeanDefinition(holder.getBeanName(), holder.getBeanDefinition()); for (String alias : Objects.requireNonNull(holder.getAliases())) { context.registerAlias(holder.getBeanName(), alias); } 复制代码
BeanDefinitionParser
类 这个接口就是一个对象. 是spring的xml配置中 解析xml需要使用到的. parser. 其实这个返回值没卵用. 有兴趣可以看看源码 , 分析一下为啥这个返回值没啥用. 所以返回null也行. 只要注册到context中就行了.
public interface BeanDefinitionParser { @Nullable // Element , 其实就是XML的一组标签 // ParserContext 其实就是Spring的上下文,因为xmlcontext基础了这个. BeanDefinition parse(Element element, ParserContext parserContext); } 复制代码
BeanDefinitionReader
类 这个名字 , 很显然是从什么地方读的 BeanDefinition
的.
其实主要就是俩. XmlBeanDefinitionReader
他实现了 BeanDefinition
接口.
但是 AnnotatedBeanDefinitionReader
并没有.
其主要实现就是. 一下三个方法. 其实也简单. 因为需要 BeanDefinitionRegistry
,然后拿到 Resource
去注册就行了.
BeanDefinitionRegistry getRegistry(); int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException; int loadBeanDefinitions(Resource... resources) throws BeanDefinitionStoreException; 复制代码
我们先看最熟悉的 AnnotatedBeanDefinitionReader
AnnotatedBeanDefinitionReader reader = new AnnotatedBeanDefinitionReader(context); // SringApp类作为配置类. context作为register. reader.registerBean(SringApp.class); 复制代码
xml那个 也是 , 拿着source去做就行了.
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(context); reader.loadBeanDefinitions("user.xml"); // 刷新 . 获取就行了. context.refresh(); // 内部实现比较麻烦. 所以自行去了解. User bean = context.getBean(User.class); System.out.println(bean); 复制代码
ClassPathBeanDefinitionScanner
这是一个根据类路径进行一个加载器
// 我们调用scan方法 , 其实是调用的ClassPathBeanDefinitionScanner去加载的. public void scan(String... basePackages) { Assert.notEmpty(basePackages, "At least one base package must be specified"); this.scanner.scan(basePackages); } 复制代码
他会扫描. 所有组件 . 默认过滤器是一下实现.
Candidate classes are detected through configurable type filters. The default filters include classes that are annotated with Spring's @Component, @Repository, @Service, or @Controller stereotype. 复制代码