-
如何将一个类的实例对象bean交由spring管理(注意是一个实例对象而不是一个类)
-
通过@Bean注解
-
通过FactoryBean实现(实现FactoryBean接口,重写FactoryBean.getObject方法)
- 一个FactoryBean可以产生两个对象,一个是FactoryBean本身,另一个是通过FactoryBean.getObject方法获取到的bean对象;
- 在Spring启动时时会对Bean进行初始化创建,当一个Bean实现了另一个是通过FactoryBean时,会根据 "&" + beanName去创建当前FactoryBean的bean对象,然后通过beanName去创建bean时会调用FactoryBean的getObject方法返回我们自己初始化的对象;
@Component public class MyFactoryBean implements FactoryBean { @Override public Object getObject() throws Exception { TestDemo testDemo = new TestDemo(); return testDemo; } @Override public Class<?> getObjectType() { return TestDemo.class; } }
-
调用spring的api手动注入 beanFactory.registerSingleton(String name,Object object)——直接传自己的对象
- 通过获取ApplicationContext实例对象,通过向BeanFactory对象中的一级缓存单例池中注入一个bean完成;
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(); applicationContext.register(SpringConfig.class); applicationContext.getBeanFactory().registerSingleton("b",new MyService()); applicationContext.refresh(); MyService myService = applicationContext.getBean(MyService.class); myService.printInfo();
- 通过获取ApplicationContext实例对象,通过向BeanFactory对象中的一级缓存单例池中注入一个bean完成;
-
-
spring中的bean和普通的java对象有什么区别,什么是BeanDefinition?
-
在spring框架中,Beandefition是spring容器中对bean抽象定义和描述的元数据;它包含了对应bean在初始化时所需要相关信息,比如bean的名称,类型,生命周期等;在spring中bean的创建和BeanDefition对象相关,与bean对应的class类无关;(可以通过修改beanDefinition中BeanClass从而修改bean的类型);spring会将所有的Bean对应的BeanDefinitiond对象放入在一个BeanFactory中的beanDefinitionMap中;
-
Beandefinition类中几个重要的属性
- ConstructorArgumentValues=[];主要用于存储对应beanClass构造方法需要传入的参数列表
- scope: 该bean实例化后的类型,默认为singleton 单例bean;
- layzInit=false;是否为懒加载的
- Object beanClass; 该beandefinition是用来创建哪一个类类型的;
- MutablePropertyValues propertyValues 当前bean依赖注入需要进行属性填充的属性对应值列表(key-value)
- 其他属性
-
如何实现手动往spring容器注入一个BeanDefinition
-
通过BeanFactoryPostProcessor
-
通过BeanDefinitionRegistryPostProcessor
-
通过ImportBeanDefinitionRegistrar
-
-
-
什么是BeanFactoryPostProcessor,BeanDefinitionRegistryPostProcessor它们的工作原理是什么
- BeanFactoryPostProcessor是BeanFactory的后置处理器,是spring扩展点之一,它允许我们在 Spring容器初始化启动过程中允许程序员对BeanFactory组件进行全局设置,修改,添加beanDefition;设置忽略某个类型,某个接口等功能。
- BeanDefinitionRegistryPostProcessor继承了BeanFactoryPostProcessor,它也是spring扩展点之一,并且他的执行时机会比BeanFactoryPostProcessor靠前一点;所以侧重于动态添加BeanDefition对象到容器中
- BeanDefinitionRegistryPostProcessor继承了BeanFactoryPostProcessor,但二者都能向容器添加BeanDefinition对象;但由于spring容器初始化顺序的时机不同(如果在bean的扫描之后添加),会导致BeanDefinitionRegistryPostProcessor与BeanFactoryPostProcesso添加的BeanDefinition对象是一个普通bean并且是个不完整的bean,可能存在某种未知的错误;
-
BeanFactoryPostProcessor,BeanDefinitionRegistryPostProcessor两者的执行顺序(invokeBeanFactoryPostProcessor方法执行BeanFactory的后置处理器)
-
先说结论:在beanFactory后置处理器中执行顺序
-
1.首先执行api手动注册的BeanDefinitionRegistryPostProcessor的子类postProcessBeanDefinitionRegistry方法;
-
2.在执行扫描出来的BeanDefinitionRegistryPostProcessor,按照优先级PriorityOrdered > Order > 二者都未实现的顺序执行postProcessBeanDefinitionRegistry方法;
-
3.执行所有子类BeanDefinitionRegistryPostProcessor的父类中postProcessBeanFactory方法
-
4.执行API手动注册的BeanFactoryPostProcessor的postProcessBeanFactory方法
-
5.最后执行扫描出来的BeanFactoryPostProcessor列表,按照优先级PriorityOrdered > Order > 二者都未实现的顺序执行postProcessBeanFactory方法;
-
所以由于BeanFactoryPostProcessor与BeanDefinitionRegistryPostProcessor执行的顺序时机不对,可能会出现注入的bean是个残次品,会出现某种未知的异常;(例如在ConfigurationClassPostProcessor执行之后扫描到的,就无法完成spring中的渲染)
-
public static void invokeBeanFactoryPostProcessors( ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) { //存放已经处理完的BeanFactoryPostProcessor以及子类BeanDefinitionRegistryPostProcessor,防止重复执行; //不会存储通过api提供的, Set<String> processedBeans = new HashSet<>(); if (beanFactory instanceof BeanDefinitionRegistry) { BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory; //存放所有实现了BeanFactoryPostProcessor的bean List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>(); //存放所有实现了BeanDefinitionRegistryPostProcessor的bean; List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>(); for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) { //判断api手动注入的是否是BeanDefinitionRegistryPostProcessor if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) { BeanDefinitionRegistryPostProcessor registryProcessor = (BeanDefinitionRegistryPostProcessor) postProcessor; //执行api手动注入BeanDefinitionRegistryPostProcessor的postProcessBeanDefinitionRegistry方法 registryProcessor.postProcessBeanDefinitionRegistry(registry); registryProcessors.add(registryProcessor); } else { regularPostProcessors.add(postProcessor); } } //当前需要执行的BeanDefinitionRegistryPostProcessor列表 List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>(); //第一次查找,根据类型去BeanFactory中的BeanDefinitionMap与单例池(spring内置的bean)中去查找,返回名字 String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false); for (String ppName : postProcessorNames) { if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) { //判断是否实现PriorityOrdered接口,是的话调用beanFactory.getBean获取该类的对象(不存在会自动实例化并放入单例池中SingeltonObjects) //放入当前需要执行的currentRegistryProcessors列表中 currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class)); //表示当前类执行完了 processedBeans.add(ppName); } } //排序,order接口和类名等排序 sortPostProcessors(currentRegistryProcessors, beanFactory); //合并BeanDefinitionRegistryPostProcessor列表,为了将来执行BeanDefinitionRegistryPostProcessor继承的父类BeanFactoryPostProcessor中的方法 registryProcessors.addAll(currentRegistryProcessors); //遍历列表,执行BeanDefinitionRegistryPostProcessor的postProcessBeanDefinitionRegistry子类方法 invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup()); //清空当前执行BeanDefinitionRegistryPostProcessor列表,因为下次需要继续使用 currentRegistryProcessors.clear(); //第二次查找,根据类型查找BeanDefinitionRegistryPostProcessor,容器在第一次扫描后,执行完内置BeanDefinitionRegistryPostProcessor(ConfigruationClassPostProcessor完成了spring的扫描),容器中可能会新增了一些BeanDefinitionRegistryPostProcessor; postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false); for (String ppName : postProcessorNames) { //判断扫描出来的,是否已经执行过了并且是否实现了Ordered接口 if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) { currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class)); processedBeans.add(ppName); } } //排序 sortPostProcessors(currentRegistryProcessors, beanFactory); //合并 registryProcessors.addAll(currentRegistryProcessors); //遍历执行 invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup()); //清空 currentRegistryProcessors.clear(); //循环退出标志 boolean reiterate = true; while (reiterate) { reiterate = false; //第三次或n次进行查找,根据类型查找BeanDefinitionRegistryPostProcessor;因为在第二次查找中BeanDefinitionRegistryPostProcessor.postProcessBeanDefinitionRegistry方法动态添加的BeanDefinitionRegistryPostProcessor的(未被扫描到的);在第二次查找时,可能存在未被执行的BeanDefinitionRegistryPostProcessor(未实现Ordered接口的) postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false); for (String ppName : postProcessorNames) { if (!processedBeans.contains(ppName)) { currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class)); processedBeans.add(ppName); //如果找到了,就得继续找,有可能会有新增 reiterate = true; } } sortPostProcessors(currentRegistryProcessors, beanFactory); registryProcessors.addAll(currentRegistryProcessors); invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup()); currentRegistryProcessors.clear(); } //遍历执行BeanDefinitionRegistryPostProcessor中父类的BeanFactoryPostProcessor的postProcessBeanFactory方法;(因为所有的BeanDefinitionRegistryPostProcessor中的子类方法已经执行完了) invokeBeanFactoryPostProcessors(registryProcessors, beanFactory); //遍历执行通过Api提供的BeanFactoryPostProcessor的postProcessBeanFactory方法 invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory); } else { invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory); } //查找不是通过API提供的BeanFactoryPostProcessor列表 String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false); //存放实现了priorityOrdered接口的BeanFactoryPostProcessor列表 List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>(); //存放实现了ordered接口BeanFactoryPostProcessor列表(PriorityOrdered继承了ordered接口) List<String> orderedPostProcessorNames = new ArrayList<>(); //存放未实现ordered接口和priorityOrdered接口的BeanFactoryPostProcessor列表 List<String> nonOrderedPostProcessorNames = new ArrayList<>(); for (String ppName : postProcessorNames) { if (processedBeans.contains(ppName)) { //判断是否执行 } else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) { //判断是否实现了PriorityOrdered接口,如果实现了实例化并放入priorityOrderedPostProcessors列表中 priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class)); } else if (beanFactory.isTypeMatch(ppName, Ordered.class)) { //判断是否实现Ordered,是的话放入orderedPostProcessorNames列表,但未进行实例化 orderedPostProcessorNames.add(ppName); } else { nonOrderedPostProcessorNames.add(ppName); } } //排序 sortPostProcessors(priorityOrderedPostProcessors, beanFactory); //第一,首先遍历执行已经实现了priorityOrdered接口的BeanFactoryPostProcessor的postProcessBeanFactory方法 invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory); List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size()); for (String postProcessorName : orderedPostProcessorNames) { //再遍历创建已经实现ordered接口的BeanFactoryPostProcessor对象 orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class)); } sortPostProcessors(orderedPostProcessors, beanFactory); //第二,遍历执行已经实现了Ordered接口的BeanFactoryPostProcessor的postProcessBeanFactory方法 invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory); List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size()); for (String postProcessorName : nonOrderedPostProcessorNames) { //最后,执行创建未实现ordered接口和priorityOrdered接口的BeanFactoryPostProcessor nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class)); } //最后,遍历执行未实现了Ordered接口的BeanFactoryPostProcessor的postProcessBeanFactory方法 invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory); beanFactory.clearMetadataCache(); } -
-
BeanFactoryPostProcessor中实现在自动注入模式下忽略某个类型的注入
-
void ignoreDependencyType(Class<?> type);在自动注入的模型下忽略type类型bean的注入,对所有bean都生效;
-
void ignoreDependencyInterface(Class<?> ifc);一般情况下ifc是个接口并且ifc里面有一个setter方法;如果某个bean实现了 ifc接口,那么必然会重写里面的setter,而重写的这个setter就不会被自动注入;主要作用也是忽略某个类型的bean的自动注入;但是ignoreDependencyInterface不能对所有bean生效,你得实现ifc接口才能对忽略的设置生效;(例如spring中aware接口)
@Slf4j public class A implements BeanFactoryPostProcessor { @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { log.error("A类 - BeanFactoryPostProcessor.postProcessBeanFactory()"); beanFactory.ignoreDependencyType(B.class); beanFactory.ignoreDependencyInterface(K.class); } } -
-
如何确保postProcessBeanDefinitionRegistry方法对BeanDefinitionRegistryPostProcessor类型的beanDefition的修改最大化生效
- 同级别BeanDefinitionRegistryPostProcessor修改一个BeanDefinitionRegistryPostProcessor的beanDefition会失效(对普通类的修改不会失效),因为spring是找出同级别的bean直接实例化存到集合当中,然后一起执行,这样在执行第一个的时候如果修改了第二个的bd则无效;但是对普通类的修改就不会失效了,因为普通类实例化特别靠后,你修改一定会生效;如果你一定需要修改一个BeanDefinitionRegistryPostProcessor对应的的BeanDefition,最好提高当前子类的级别优先级(PriorityOrdered > order > 无接口实现);
-
mybatis是怎么和spring进行整合的?是如何将Mapper代理对象MapperProxy交由spring容器中的
- mybatis提供一了一个mybatis-spring的插件包实现了与spring的整合。2.0插件包通过MapperScan注解将MapperScannerRegistrar(实现了ImportBeanDefinitionRegistrar接口)中注入一个MapperScannerConfigurer(实现了BeanDefinitionRegistryPostProcessor)的BeanDefition对象,在spring容器初始化过程中会调用ImportBeanDefinitionRegistrar.registerBeanDefinitions方法后,将扫描到的Mapper对于的beanDefition对象就行修改,将beanClass设置成MapperFactoryBean(实现了FactoryBean),并将当前bean的beanclass对象设置成ConstructorArgumentValues中的属性值;最后将该BeanDefinition的注入模式设置为AbstractBeanDefinition.AUTOWIRE_BY_TYPE;
-
mybatis-spring为什么采用ImportBeanDefinitionRegistrar来实现扩展,而不直接使用BeanDefinitionRegistryPostProcessor来完成spring的整合;
- ImportBeanDefinitionRegistrar.registerBeanDefinitions的执行时机比较靠前,在ConfigurationClassPostProcessor中spring内置的BeanDefinitionRegistryPostProcessor实现了PriortyOrdered接口完成了ImportBeanDefinitionRegistrar的调用,执行完后还能spring还能完成bean的渲染;所以生成的bean是一个功能完整的bean;
- ImportBeanDefinitionRegistrar.registerBeanDefinitions可以将MapperScan注解的元数据信息给到Mybatis,从而实现用户自定义配置mybatis配置信息;
-
spring中的容器BeanFactory与ApplicationContext?两者的区别是什么,BeanFactory与FactoryBean的区别是什么?
- spring框架中存在多种容器,大致可以分为两种BeanFactory与ApplicationContext;spring官网描述说通常情况建议使用ApplicationContext而不是BeanFactory;因为ApplicationContext的功能比BeanFactory更加强大和完善;
-
两者都支持bean的实例化
- BeanFactory也能完成bean的实例化,bean的依赖,但是得通过调用getBean方法才会去创建(可以说是懒加载的),而ApplicationContext会自动创建非懒加载的bean;
-
BeanFactory不支持生命周期管理
-
BeanFactory不支持自动注册BeanPostProcessor和自动注册BeanFactoryPostProcessor
-
BeanFactory不支持国际化和不支持事件发布
-
- spring框架中存在多种容器,大致可以分为两种BeanFactory与ApplicationContext;spring官网描述说通常情况建议使用ApplicationContext而不是BeanFactory;因为ApplicationContext的功能比BeanFactory更加强大和完善;