BeanDefinition
顾名思义就是 Bean的定义, 那么他应该包含Bean的元信息. 因此就是这个意思. 对的他就是这么个意思.java
Spring中对于BeanFactory生成的Bean所有由这个去定义的.spring
咱们看看Spring提供了什么的BeanDefinition工具
基本就是上图所示的几种. 大部分都是由 abs组成的. 另外一个是内部类. 咱们不考虑 ,ui
那么咱们就学学如何使用吧.this
GenericBeanDefinition
它是个通用的.spa
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);
}
}
复制代码
其实还能够继承的code
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.cdn
// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);
// 而后进入在
// Instantiate all remaining (non-lazy-init) singletons.
beanFactory.preInstantiateSingletons();
// 主要流程就是去注册Bean. 到 , 详细代码能够看看. 其实很简单的.
复制代码
RootBeanDefinition
和 ChildBeanDefinition
这俩成双成对的. 你说不是吗. root节点不能有父类 , 其中儿子节点, 必须有父类 . 用法上和上面那个没啥区别.xml
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.
复制代码
BeanDefinitionRegistry
比较核心. 毕竟是注册BeanDefinition用的.
核心接口方法
void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws BeanDefinitionStoreException;
复制代码
通常咱们常见的SpringApplication 默认就是一个实现好的register.