目录
Bean工厂后处理器-BeanFactoryPostProcessor
- //
- // Source code recreated from a .class file by IntelliJ IDEA
- // (powered by FernFlower decompiler)
- //
-
- package org.springframework.beans.factory.config;
-
- import org.springframework.beans.BeansException;
-
- @FunctionalInterface
- public interface BeanFactoryPostProcessor {
- void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
- }
创建一个实现类(修改beanDefinition对象)
- package com.example.PostProcessor;
-
- import org.springframework.beans.BeansException;
- import org.springframework.beans.factory.config.BeanDefinition;
- import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
- import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
-
- public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
- @Override
- public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
- System.out.println("beanDefinitionMap填充完毕后会回调该方法");
- // todo 修改Map集合中的BeanDefinition对象
- BeanDefinition userService = beanFactory.getBeanDefinition("userService");
- userService.setBeanClassName("com.example.DAO.Impl.UserDAOImpl");
-
- }
- }
测试类
- package com.example.Test;
-
-
- import org.springframework.context.support.ClassPathXmlApplicationContext;
- public class TestApplicationContext {
- public static void main(String[] args) {
- ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("application.xml");
- System.out.println(context.getBean("userService"));
- }
- }
运行结果如下

- package com.example.PostProcessor;
-
- import org.springframework.beans.BeansException;
- import org.springframework.beans.factory.config.BeanDefinition;
- import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
- import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
- import org.springframework.beans.factory.support.DefaultListableBeanFactory;
- import org.springframework.beans.factory.support.RootBeanDefinition;
-
- public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
- @Override
- public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
- // todo 向Map集合中添加一个BeanDefinition对象,即在配置文件中没有注册
- // 创建一个新的beanDefinition对象
- BeanDefinition beanDefinition = new RootBeanDefinition();
- // 设置bean对应的类
- beanDefinition.setBeanClassName("com.example.DAO.Impl.UserDAOImpl");
- DefaultListableBeanFactory listableBeanFactory = (DefaultListableBeanFactory) beanFactory;
- // 添加该beanDefinition对象
- listableBeanFactory.registerBeanDefinition("UserDAO", beanDefinition);
- }
- }
在配置文件中没有配置UserDAO了
测试类
- package com.example.Test;
-
-
- import com.example.DAO.Impl.UserDAOImpl;
- import org.springframework.context.support.ClassPathXmlApplicationContext;
-
- public class TestApplicationContext {
- public static void main(String[] args) {
- ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("application.xml");
-
- System.out.println(context.getBean(UserDAOImpl.class));
- }
- }
运行结果

beanDefinition对象成功添加
- //
- // Source code recreated from a .class file by IntelliJ IDEA
- // (powered by FernFlower decompiler)
- //
-
- package org.springframework.beans.factory.support;
-
- import org.springframework.beans.BeansException;
- import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
-
- public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor {
- void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException;
- }
创建一个类实现后处理器BeanFactoryPostProcessor的子接口BeanDefinitionRegistryPostProcessor(记得将该类注册到Spring容器中)
- package com.example.PostProcessor;
-
- import org.springframework.beans.BeansException;
- import org.springframework.beans.factory.config.BeanDefinition;
- import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
- import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
- import org.springframework.beans.factory.support.BeanDefinitionRegistry;
- import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
- import org.springframework.beans.factory.support.DefaultListableBeanFactory;
- import org.springframework.beans.factory.support.RootBeanDefinition;
-
- public class MyBeanFactoryPostProcessor02 implements BeanDefinitionRegistryPostProcessor {
- @Override
- public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
- // 注册beanDefinition
- BeanDefinition beanDefinition = new RootBeanDefinition();
- beanDefinition.setBeanClassName("com.example.DAO.Impl.UserDAOImpl");
- registry.registerBeanDefinition("UserDAO", beanDefinition);
- }
- @Override
- public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
-
- }
- }
实现添加beanDefiniton就会简单很多
测试类
- package com.example.Test;
-
-
- import com.example.DAO.Impl.UserDAOImpl;
- import org.springframework.context.support.ClassPathXmlApplicationContext;
-
- public class TestApplicationContext {
- public static void main(String[] args) {
- ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("application.xml");
- System.out.println(context.getBean(UserDAOImpl.class));
- }
- }
运行结果如下

完整流程图

- package com.example.Anno;
-
- import java.lang.annotation.ElementType;
- import java.lang.annotation.Retention;
- import java.lang.annotation.RetentionPolicy;
- import java.lang.annotation.Target;
-
- @Target(ElementType.TYPE) // 设该注解的使用范围
- @Retention(RetentionPolicy.RUNTIME) // 设置该注解运行期间可见
- public @interface MyComponent {
- String value(); //用于设置注解的值
- }
工具类
- package com.example.Utils;
-
- import com.example.Anno.MyComponent;
- import org.springframework.core.io.Resource;
- import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
- import org.springframework.core.io.support.ResourcePatternResolver;
- import org.springframework.core.type.classreading.CachingMetadataReaderFactory;
- import org.springframework.core.type.classreading.MetadataReader;
- import org.springframework.core.type.classreading.MetadataReaderFactory;
- import org.springframework.util.ClassUtils;
-
- import java.util.HashMap;
- import java.util.Map;
-
- public class BaseClassScanUtils {
-
- //设置资源规则
- private static final String RESOURCE_PATTERN = "/**/*.class";
-
- public static Map
scanMyComponentAnnotation(String basePackage) { -
- //创建容器存储使用了指定注解的Bean字节码对象
- Map
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) {
- //用于读取类信息
- MetadataReader reader = refractory.getMetadataReader(resource);
- //扫描到的class
- String classname = reader.getClassMetadata().getClassName();
- Class> clazz = Class.forName(classname);
- //判断是否属于指定的注解类型
- if(clazz.isAnnotationPresent(MyComponent.class)){
- //获得注解对象
- MyComponent annotation = clazz.getAnnotation(MyComponent.class);
- //获得属value属性值
- String beanName = annotation.value();
- //判断是否为""
- if(beanName!=null&&!beanName.equals("")){
- //存储到Map中去
- annotationClassMap.put(beanName,clazz);
- continue;
- }
-
- //如果没有为"",那就把当前类的类名作为beanName
- annotationClassMap.put(clazz.getSimpleName(),clazz);
-
- }
- }
- } catch (Exception exception) {
- }
-
- return annotationClassMap;
- }
-
- public static void main(String[] args) {
- Map
stringClassMap = scanMyComponentAnnotation("com.itheima"); - System.out.println(stringClassMap);
- }
- }
使用注解来注册为Bean对象的类
- package com.example.Beans;
-
- import com.example.Anno.MyComponent;
-
- @MyComponent("otherBean")
- public class otherBeans {
- }
在配置文件中没有配置该类作为bean对象
后工厂处理器类(该类要交给Spring容器管理)
- package com.example.PostProcessor;
-
-
- import com.example.Utils.BaseClassScanUtils;
- import org.springframework.beans.BeansException;
- import org.springframework.beans.factory.config.BeanDefinition;
- import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
- import org.springframework.beans.factory.support.BeanDefinitionRegistry;
- import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
- import org.springframework.beans.factory.support.RootBeanDefinition;
-
- import java.util.Map;
-
- public class MyComponentBeanFactoryProcessor implements BeanDefinitionRegistryPostProcessor {
- @Override
- public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
- // 通过工具去扫描指定包及其子包下的所有类,收集使用@MyComponent注解的类,放在Map集合中
- Map
MyComponentAnnotationMap = BaseClassScanUtils.scanMyComponentAnnotation("com.example"); - // 遍历Map,组装BeanDefinition进行注册
- MyComponentAnnotationMap.forEach((beanName,clazz)->{
- // 获取beanClassName
- String beanClassName = clazz.getName();
- // 创建beanDefinition
- BeanDefinition beanDefinition = new RootBeanDefinition();
- beanDefinition.setBeanClassName(beanClassName);
- // 注册
- registry.registerBeanDefinition(beanName,beanDefinition);
- });
-
- }
-
- @Override
- public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
-
- }
- }
通过后工厂处理器类来将标记了自己创建的@MyComponent注解的类创建为beanDefinition对象后添加到beanDefinitionMap集合中。
测试类
- package com.example.Test;
-
-
- import com.example.Beans.otherBeans;
- import org.springframework.context.support.ClassPathXmlApplicationContext;
-
- public class TestApplicationContext {
- public static void main(String[] args) {
- ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("application.xml");
- System.out.println(context.getBean(otherBeans.class));
- }
- }
运行结果

运行成功~
使用注解注册bean的原理
最主要是通过Bean工厂后处理器进行实现的,通过工具类获取到添加了注解的类的集合后,在后处理器中,对扫描结果进行遍历,然后生成对对应的beanDefinition对象后,注册到beanDefinitonMap集合后即可。