俗话说“磨刀不误砍柴工”,我们本节教程的目的是对Spring的一些核心概念进行扫盲,避免在进入正题讲解的时候由于某些概念还不理解,影响学习效率。
1、BeanDefination
- BeanDefination标识Bean定义,用来描述一个Bean的特点,比如:
- class,表示Bean类型
- scpoe,表示Bean的作用域,是单例还是原型等
- lazyInit,表示Bean是不是懒加载
- initMethodName,表示Bean初始化时要执行的方法
- destroyMethodName,表示bean销毁时候执行的方法
- 还有很多……
通过
用法如下:Dog类上边并没有加@Component等注解,我们自定义Beandefination,一样可以将Dog注册为Bean。
public class Dog {
void say() {
System.out.println("hi i am a dog name is wangwang");
}
}
@Configuration
@ComponentScan("com.ioc.tuing.impl")
public class MainStart {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MainStart.class);
AbstractBeanDefinition abstractBeanDefinition =
BeanDefinitionBuilder.genericBeanDefinition().getBeanDefinition();
abstractBeanDefinition.setBeanClass(Dog.class);
context.registerBeanDefinition("dog", abstractBeanDefinition);
Dog dog = (Dog)context.getBean("dog");
dog.say();
}
}
2、BeanDefinitionReader
接下来,我们介绍BeanDefination的读取器:BeanDefinationReader,我们在实际工作中其实用的很少,但是在Spring源码里,用的非常多,相当于Spring源码的基础设施。
- AnnotatedBeanDefinitionReader
它可以直接把某个类转换为BeanDefinition,并且会解析该类上的注解,比如:Dog类是个普通类,我们可以用AnnotatedBeanDefinitionReader将Dog.class解析为BeanDefinition。注意:它能解析的注解是:@Conditional,@Scope、@Lazy、@Primary、@DependsOn、@Role、@Description
public class Dog {
void say() {
System.out.println("hi i am a dog name is wangwang");
}
}
@Configuration
@ComponentScan("com.ioc.tuing.impl")
public class MainStart {
public static void main(String[] args) {
// AnnotatedBeanDefinitionReader
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MainStart.class);
AnnotatedBeanDefinitionReader annotatedBeanDefinitionReader = new AnnotatedBeanDefinitionReader(context);
// 将Dog.class解析为BeanDefinition
annotatedBeanDefinitionReader.register(Dog.class);
Dog dog = (Dog)context.getBean("dog");
dog.say();
}
}
- XmlBeanDefinitionReader
它可以解析
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="memberXML" class="com.ioc.tuing.impl.MemberXML"></bean>
</beans>
public class MemberXML {
void say() {
System.out.println("i am MemberXML");
}
}
@Configuration
@ComponentScan("com.ioc.tuing.impl")
public class MainStart {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MainStart.class);
XmlBeanDefinitionReader xmlBeanDefinitionReader = new XmlBeanDefinitionReader(context);
// 解析spring.xml里的<bean/>标签
int i = xmlBeanDefinitionReader.loadBeanDefinitions("spring.xml");
MemberXML memberXML = (MemberXML)context.getBean("memberXML");
memberXML.say();
}
}
- ClassPathBeanDefinitionScanner
ClassPathBeanDefinitionScanner是扫描器,但是它的作用和BeanDefinitionReader类似,它可以进行扫描,扫描某个包路径,对扫描到的类进行解析,比如,扫描到的类上如果存在@Component注解,那么就会把这个类解析为一个BeanDefinition,比如:
public class MainStart {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
context.refresh();
ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(context);
scanner.scan("com.ioc");
User user = (User)context.getBean("user");
user.say();
}
}
3、BeanFactory
BeanFactory表示Bean工厂,负责创建Bean,并且提供获取Bean的API。
而ApplicationContext是BeanFactory的一种,在Spring源码中,它是这样的:
public interface ApplicationContext extends EnvironmentCapable, ListableBeanFactory, HierarchicalBeanFactory,
MessageSource, ApplicationEventPublisher, ResourcePatternResolver {
......
}
我们发现,ApplicationContext继承了ListableBeabFactory、HierarchicalBeanFactory,而这两个接口都继承自BeanFactory接口。所以,ApplicationContext拥有BeanFactory的所有功能,除此之外还有用其他功能,比如:MessageSource表示国际化,ApplicationEventPublisher表示事件发布,EnvironmentCapable表示获取环境变量,等等。
在Spring源码中,BeanFactory有一个非常重要的实现类:DefaultListableBeanFactory,所以我们可以使用DefaultListableBeanFactory作为容器,而不使用ApplicationContext的实现类作为容器,比如:
@Configuration
@ComponentScan("com.ioc.tuing.impl")
public class MainStart {
public static void main(String[] args) {
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition().getBeanDefinition();
beanDefinition.setBeanClass(User.class);
beanFactory.registerBeanDefinition("user", beanDefinition);
User user = (User)beanFactory.getBean("user");
user.say();
}
DefaultListableBeanFactory拥有的功能如下:
- AliasRegistry:支持别名功能,一个名字可以对应多个别名
- BeanDefinitionRegistry:可以注册、保存、移除、获取某个BeanDefinition
- BeanFactory:Bean工厂,可以根据某个bean的名字、或类型、或别名获取某个Bean对象
- SingletonBeanRegistry:可以直接注册、获取某个单例Bean
- SimpleAliasRegistry:它是一个类,实现了AliasRegistry接口中所定义的功能,支持别名功能
- ListableBeanFactory:在BeanFactory的基础上,增加了其他功能,可以获取所有BeanDefinition的beanNames,可以根据某个类型获取对应的beanNames,可以根据某个类型获取{类型:对应的Bean}的映射关系
- HierarchicalBeanFactory:在BeanFactory的基础上,添加了获取父BeanFactory的功能
- DefaultSingletonBeanRegistry:它是一个类,实现了SingletonBeanRegistry接口,拥有了直接注册、获取某个单例Bean的功能
- ConfigurableBeanFactory:在HierarchicalBeanFactory和SingletonBeanRegistry的基础上,添加了设置父BeanFactory、类加载器(表示可以指定某个类加载器进行类的加载)、设置Spring EL表达式解析器(表示该BeanFactory可以解析EL表达式)、设置类型转化服务(表示该BeanFactory可以进行类型转化)、可以添加BeanPostProcessor(表示该BeanFactory支持Bean的后置处理器),可以合并BeanDefinition,可以销毁某个Bean等等功能
- FactoryBeanRegistrySupport:支持了FactoryBean的功能
- AutowireCapableBeanFactory:是直接继承了BeanFactory,在BeanFactory的基础上,支持在创建Bean的过程中能对Bean进行自动装配
- AbstractBeanFactory:实现了ConfigurableBeanFactory接口,继承了FactoryBeanRegistrySupport,这个BeanFactory的功能已经很全面了,但是不能自动装配和获取beanNames
- ConfigurableListableBeanFactory:继承了ListableBeanFactory、AutowireCapableBeanFactory、ConfigurableBeanFactory
- AbstractAutowireCapableBeanFactory:继承了AbstractBeanFactory,实现了AutowireCapableBeanFactory,拥有了自动装配的功能
DefaultListableBeanFactory:继承了AbstractAutowireCapableBeanFactory,实现了ConfigurableListableBeanFactory接口和BeanDefinitionRegistry接口,所以DefaultListableBeanFactory的功能很强大
4、ApplicationContext
上边已经提到过,ApplicationContext继承自BeanFactory,但是它比BeanFactory有更多的功能:HierarchicalBeanFactory:拥有获取父BeanFactory的功能
- ListableBeanFactory:拥有获取beanNames的功能
- ResourcePatternResolver:资源加载器,可以一次性获取多个资源(文件资源等等)
- EnvironmentCapable:可以获取运行时环境(没有设置运行时环境功能)
- ApplicationEventPublisher:拥有广播事件的功能(没有添加事件监听器的功能)
- MessageSource:拥有国际化功能
ApplicationContext有两个非常重要的实现类:
AnnotationConfigApplicationContext
ClassPathXmlApplicationContext
5、BeanPostProcessor
BeanPostProcessor表示Bean的后置处理器,也可称之为增强器,我们可以自定义一个或多个BeanPostProcessor,例:
@Component
public class MyBeanPostProcess implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if ("user".equals(beanName)) {
return bean;
}
System.out.println("postProcessBeforeInitialization" + beanName);
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if ("user".equals(beanName)) {
return bean;
}
System.out.println("postProcessAfterInitialization" + beanName);
return bean;
}
}
一个BeanPostProcessor可以在任意一个Bean的初始化之前以及初始化之后去额外的做一些用户自定义的逻辑,当然,我们可以通过判断beanName来进行针对性处理(针对某个Bean,或某部分Bean)。
我们可以通过定义BeanPostProcessor来干涉Spring创建Bean的过程。
6、BeanFactoryPostProcessor
BeanFactoryPostProcessor表示Bean工厂的后置处理器,其实和BeanPostProcessor类似,BeanPostProcessor是干涉Bean的创建过程,BeanFactoryPostProcessor是干涉BeanFactory的创建过程。比如,我们可以这样定义一个BeanFactoryPostProcessor:
@Component
public class MyBeanFactoryPostProcess implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
System.out.println("MyBeanFactoryPostProcessor...postProcessBeanFactory...");
int count = beanFactory.getBeanDefinitionCount();
String[] names = beanFactory.getBeanDefinitionNames();
System.out.println("current BeanFactory have " + count + " Bean");
System.out.println(Arrays.asList(names));
}
}
我们可以在postProcessBeanFactory()方法中对BeanFactory进行加工。