Young87

当前位置:首页 >个人收藏

聊聊spring中的工厂后置处理器

昂,有好久没有写文章了,不知从何写起…想起之前学习过的spring源码都快忘了,后续就写一写spring源码的文章吧。今天从工厂后置处理器开头,后续的文章会引出spring是如何利用工厂后置处理器去扫描bean的。

其实我一直都喜欢读一些简短精悍的文章,因为太长了看着太累,然后就没啥兴趣了…不知大家是不是也这样呢?所以我决定写点简短没有精悍的的文章~

对spring源码有兴趣的可以关注一下。

1.BeanFactoryPostProcessor

这个是spring中工厂后置器的顶级接口,里面只提供了一个方法,先看看这个接口。

public interface BeanFactoryPostProcessor {

   /**
    * Modify the application context's internal bean factory after its standard
    * initialization. All bean definitions will have been loaded, but no beans
    * will have been instantiated yet. This allows for overriding or adding
    * properties even to eager-initializing beans.
    * @param beanFactory the bean factory used by the application context
    * @throws org.springframework.beans.BeansException in case of errors
    */
   void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;

}

这些注释大概意思就是:提供了一个bean工厂,所有的bean都已经加载了,但是还没有实例化,这样你就在bean实例化之前为所欲为了~比如添加、修改bean的属性。

举个栗子:

这里有一个car的类,添加上它的:

@Component
public class Car {
   private String name;
   private Double price;

   public void setName(String name) {
      this.name = name;
   }

   public void setPrice(Double price) {
      this.price = price;
   }

   @Override
   public String toString() {
      return "Car{" +
            "name='" + name + '\'' +
            ", price=" + price +
            '}';
   }
}

然后自定义一个工厂后置处理器:

@Component
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {

   @Override
   public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
      BeanDefinition benzCarBeanDefinition = beanFactory.getBeanDefinition("car");
      //属性
      MutablePropertyValues propertyValues = benzCarBeanDefinition.getPropertyValues();
      //会调用bean中的set方法
      propertyValues.add("name","奔驰c200l");
      propertyValues.add("price",300000.00);
   }
}

需要写一个配置类,定义需要扫描的包:

@Configuration
@ComponentScan("test")
public class MyConfiguration {
}

然后写一个测试类:

public class Test {

   public static void main(String[] args) {
      AnnotationConfigApplicationContext context = new 			    AnnotationConfigApplicationContext(MyConfiguration.class);
      Car car = (Car) context.getBean("car");
      System.out.println(car);
     //输出 Car{name='奔驰c200l', price=300000.0}
   }
}

最后的输出中,car的name 和 price都被赋予了值。

2.BeanDefinitionRegistryPostProcessor

这个接口继承了上面的BeanFactoryPostProcessor,是BeanFactoryPostProcessor的扩展,看看这个接口:

public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor {

   /**
    * Modify the application context's internal bean definition registry after its
    * standard initialization. All regular bean definitions will have been loaded,
    * but no beans will have been instantiated yet. This allows for adding further
    * bean definitions before the next post-processing phase kicks in.
    * @param registry the bean definition registry used by the application context
    * @throws org.springframework.beans.BeansException in case of errors
    */
   void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException;

}

这个接口的方法,提供了一个registry的参数,这是一个注册器,可以用这个注册器搞一些注册的事情,动态去注册bean。

再举个栗子:

自定义一个BeanDefinitionRegistryPostProcessor:

@Component
public class MyBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {
   /**
    * 扩展的方法:提供了一个注册器,可以动态的去注册bean
    * @param registry the bean definition registry used by the application context
    * @throws BeansException
    */
   @Override
   public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
      for (int i = 0; i < 10; i++) {
         BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(Car.class);
         builder.addPropertyValue("name", "奔驰_" + i);
         registry.registerBeanDefinition("car" + i, builder.getBeanDefinition());
      }
      System.out.println("动态注入bean完成");
   }

   /**
    * 父类中的方法  #postProcessBeanFactory  可以修改、设置 bean的属性
    * @param beanFactory the bean factory used by the application context
    * @throws BeansException
    */
   @Override
   public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {

   }
}

然后写一个测试类,看看是不是往spring容器中注入了10个car?

public class Test {

   public static void main(String[] args) {
      AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MyConfiguration.class);
      Map<String, Car> beansOfType = context.getBeansOfType(Car.class);
      beansOfType.forEach((k,v)->{
         System.out.println(k+">>>"+v.toString());
      });
   }
}

最后看到spring容器中已经有了10个car的bean的实例了。

这篇文章对spring的工厂后置处理器简单的介绍了一下,因为spring中使用了工厂后置处理器对整个spring工程进行了扫描,对bean的解析,一些注解的处理,个人感觉工厂后置处理器是spring源码阅读必须知道的东西,比较重要。

下期文章,会讲spring是如何利用工厂后置处理器对整个工程进行扫描的,感兴趣的可以关注一下~也可以微信搜索「山主」,第一时间阅读最新文章。

除特别声明,本站所有文章均为原创,如需转载请以超级链接形式注明出处:SmartCat's Blog

上一篇: 如何学习Python呢?那么新手要怎么入门呢?【小白必看,内含学习路线】

下一篇: Windows域策略 设置客户端服务启动状态 【全域策略生效】

精华推荐