BeanDefinition
BeanDefinition表示Bean定义,BeanDefinition中存在很多属性用来描述一个Bean的特点。比如:
- class,表示Bean类型
- scope,表示Bean作用域,单例或原型等
- lazyInit:表示Bean是否是懒加载
- initMethodName:表示Bean初始化时要执行的方法
- destroyMethodName:表示Bean销毁时要执行的方法
- 还有很多...
在Spring中,我们经常会通过以下几种方式来定义Bean:
- <bean/>
- @Bean
- @Component(@Service,@Controller)
这些,我们可以称之申明式定义Bean。
我们还可以编程式定义Bean,那就是直接通过BeanDefinition,比如:
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
// 生成一个BeanDefinition对象,并设置beanClass为User.class,并注册到ApplicationContext中
AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition().getBeanDefinition();
// Bean类型
beanDefinition.setBeanClass(User.class);
// 作用域
beanDefinition.setScope("singleton");
// 懒加载
beanDefinition.setLazyInit(true);
// 注册bean定义 beanName和Bean类型
context.registerBeanDefinition("user", beanDefinition);
System.out.println(context.getBean("user"));
User user = (User) context.getBean("user");
user.test();
}
实际中用注解实现,底层是这么实现的。
BeanDefinitionReader
接下来,我们来介绍几种在Spring源码中所提供的BeanDefinition读取器(BeanDefinitionReader),这些BeanDefinitionReader在我们使用Spring时用得少,但在Spring源码中用得多,相当于Spring源码的基础设施。
AnnotatedBeanDefinitionReader
可以直接把某个类转换为BeanDefinition,并且会解析该类上的注解,比如
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
AnnotatedBeanDefinitionReader annotatedBeanDefinitionReader = new AnnotatedBeanDefinitionReader(context);
// 将User.class解析为BeanDefinition
annotatedBeanDefinitionReader.register(User.class);
System.out.println(context.getBean("user"));
User user = (User) context.getBean("user");
user.test();
}
比起上面的BeanDefinition,省去了很多代码。
register方法,底层是构造BeanDefinition,解析处理类上的注解。
AnnotatedBeanDefinitionReader的构造器,this()方法,会创建AnnotatedBeanDefinitionReader。
AnnotatedBeanDefinitionReader能解析的注解是:@Conditional,@Scope、@Lazy、@Primary、@DependsOn、@Role、@Description。
XmlBeanDefinitionReader
可以解析<bean/>标签
/**
* XmlBeanDefinitionReader 解析xml 配置的bean 不会扫描
* @param args
*/
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
XmlBeanDefinitionReader xmlBeanDefinitionReader = new XmlBeanDefinitionReader(context);
int i = xmlBeanDefinitionReader.loadBeanDefinitions("spring.xml");
System.out.println(context.getBean("user"));
User user = (User) context.getBean("user");
user.test();
}
i是数量,解析出来一个。
ClassPathBeanDefinitionScanner
ClassPathBeanDefinitionScanner是扫描器,但是它的作用和BeanDefinitionReader类似,它可以进行扫描,扫描某个包路径,对扫描到的类进行解析,比如,扫描到的类上如果存在@Component注解,那么就会把这个类解析为一个BeanDefinition,比如:
/**
* ClassPathBeanDefinitionScanner BeanDefinition扫描器 扫描指定目录下@Component注解修饰的类 创建BeanDefinition bean对象
* @param args
*/
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
context.refresh();
ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(context);
scanner.scan("com.zhouyu");
System.out.println(context.getBean("orderService"));
}
从源码可见,AnnotationConfigApplicationContext既有扫描又有直接注册功能。