bean实例化的基本流程
Spring容器在进行初始化时,会将xml配置的<bean>
标签的信息封装成一个BeanDefinition对象,所有的BeanDefinition存储到一个名为beanDefinitionMap
的Map集合中去,Spring框架对该Map进行遍历,使用反射创建Bean实例对象,创建好的Bean对象存储到一个名为singletonObjects
的Map集合中,当调用getBean方法时,从该Map集合中取出Bean实例对象
spring的后处理器
# Spring的后处理器是Spring对外开发的重要扩展点,允许我们介入到bean的整个实例化流程中来
# 以达到动态注册/修改BeanDefinition,以及动态修改bean的作用
# 注册BeanDefinition:向BeanDefinitionMap中添加一个BeanDefinition
# Spring主要有两种后处理器:
# BeanFactoryPostProcessor:Bean工厂后处理器,BeanDefinitionMap填充完毕之后,Bean实例化之前执行(执行一次)
# BeanPostProcessor:Bean后处理器,某一个Bean实例化之后,填充到单例池singletonObjects之前执行(执行多次)
BeanFactoryPostProcessor
是一个接口规范,实现了该接口的类只要交给Spring容器管理,Spring就会回调该接口的方法
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor{
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory){
System.out.println("beanFactoryPostProcessor...");
// 修改某个BeanDefinition
BeanDefinition beanDefinition = beanFactory.getBeanDefinition("userService");
beanDefinition.setBeanClassName("cn.guet.service.xxx");
// 注册一个BeanDefinition
BeanDefinition beanDefinition1 = new RootBeanDefinition();
beanDefinition.setBeanClassName("cn.guet.service.xxx");
DefaultListableBeanFactory defaultListableBeanFactory = (DefaultListableBeanFactory) beanFactory;
defaultListableBeanFactory.registerBeanDefinition("xxx",beanDefinition1);
}
}
<bean id="myBeanFactoryPostProcessor" class="cn.guet.main.MyBeanFactoryPostProcessor"></bean>
Spring提供了BeanFactoryPostProcessor的子接口BeanDefinitionRegistryPostProcessor专门用于注册BeanDefinition操作
自定义@Component
定义一个注解以及扫描收集指定包下的所有被标注的类
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyComponent {
String value();
}
public class ScanBeanUtils {
//设置资源规则
private static final String RESOURCE_PATTERN = "/**/*.class";
public static Map<String, Class> scanMyComponentAnnotation(String basePackage) {
// 存储使用了指定注解的Bean字节码对象
Map<String, Class> annotationClassMap = new HashMap<>();
// spring工具类,获取指定路径下的全部类
ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver();
try {
String pattern = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +
ClassUtils.convertClassNameToResourcePath(basePackage) + RESOURCE_PATTERN;
Resource[] resources = resourcePatternResolver.getResources(pattern);
// MetadataReader的工厂类
MetadataReaderFactory refractory = new CachingMetadataReaderFactory(resourcePatternResolver);
for (Resource resource : resources) {
// 读取每个resource的信息
MetadataReader reader = refractory.getMetadataReader(resource);
String classname = reader.getClassMetadata().getClassName();
Class<?> cls = Class.forName(classname);
// 将标注了的放到Map中
if(cls.isAnnotationPresent(MyComponent.class)){
MyComponent annotation = cls.getAnnotation(MyComponent.class);
String beanName = annotation.value();
if(!beanName.equals("")){
annotationClassMap.put(beanName,cls);
} else {
annotationClassMap.put(cls.getSimpleName(),cls);
}
}
}
} catch (Exception exception) {
}
return annotationClassMap;
}
}
使用后处理器,注册BeanDefinition到Map中,并进行测试
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor{
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
Map<String, Class> classMap = ScanBeanUtils.scanMyComponentAnnotation("cn.guet");
classMap.forEach((beanName,cls) -> {
String className = cls.getName(); // 全限定名
BeanDefinition beanDefinition = new RootBeanDefinition();
beanDefinition.setBeanClassName(className);
// 注册到map中
DefaultListableBeanFactory beanFactory1 = (DefaultListableBeanFactory) beanFactory;
beanFactory1.registerBeanDefinition(beanName,beanDefinition);
});
}
}
<bean id="myBeanFactoryPostProcessor" class="cn.guet.main.MyBeanFactoryPostProcessor"></bean>
// 测试
ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");
Object userService = ctx.getBean("userService");
System.out.println(userService);