文章源自JAVA秀-https://www.javaxiu.com/19883.html
回顾:通过前面的章节的了解,我们又了解了InstantiationAwareBeanPostProcessor接口的基本使用,当我们想要介入一个bean的实例化和初始化的各个环节的时候,只需要写一个创建一个类实现InstantiationAwareBeanPostProcessor接口,即可灵活的进行一些自定义的业务逻辑处理。本章节我们将学习一个新的接口,就是BeanFactoryPostProcessor接口 文章源自JAVA秀-https://www.javaxiu.com/19883.html
文章源自JAVA秀-https://www.javaxiu.com/19883.html
1. BeanFactoryPostProcessor接口的基本介绍
一、通过前面的一些章节的知识介绍,我们基本上可以确定一个观念了,那就是BeanFactory是spring落地到代码层面的基础实现,也就是标配版本的spring,提供spring最基础和最核心的功能;而ApplicationContext是spring落地到代码层面的丰富实现,也就是豪华版本的spring,不但提供spring最基础和最核心的功能,还提供一些我们业务开发过程中的常用扩展功能。文章源自JAVA秀-https://www.javaxiu.com/19883.html
二、在spring的源码中,实际上ApplicationContext是间接的持有一个BeanFactory对象的。也就是说基于ApplicationContext的spring容器,在启动该过程中,一定是要创建并且初始化一个BeanFactory对象的。那么问题来了,在beanFactory对象被创建后,开发者希望自己能介入到beanFactory的
初始化过程中去,这个也是可以的。BeanFactoryPostProcessor接口就是spring提供的一个扩展机制,允许开发者在spring的启动过程中,有机会参与到beanFactory对象的初始化过程中去。一个常用的使用场景就是我们基于代码动态的注册一个bean信息到beanFactory中去,下面我们看看这个到底是如何使用的。文章源自JAVA秀-https://www.javaxiu.com/19883.html
三、本接口主要包含一个重要方法:postProcessBeanFactory方法。该方法是beanFactory对象被创建后,给开发者一个扩展或者修改beanFactory对象的机会,下面我就看看如何使用这个接口。文章源自JAVA秀-https://www.javaxiu.com/19883.html
2. BeanFactoryPostProcessor接口的基本使用
第一步:创建一个User类如下:文章源自JAVA秀-https://www.javaxiu.com/19883.html
@Data
@NoArgsConstructor
@ToString
@EqualsAndHashCode
public class User implements Serializable {
private static final long serialVersionUID = 4800166777883697833L;
private Long id;
private String name;
private String identity;
private String mobile;
private String bankcard;
private Integer age;
private Integer gender;
}
第二步:创建一个接口和接口实现类如下:文章源自JAVA秀-https://www.javaxiu.com/19883.html
public interface UserService {
User findUserById(Long id);
}
//注意,这个地方不需要这个注解了
//@Service
public class UserServiceImpl implements UserService {
private Map<Integer, String> blackListMap = new HashMap<>();
@Override
public User findUserById(Long id) {
User user = new User();
user.setId(id);
user.setName("张山");
user.setIdentity("张山");
user.setBankcard("36457736355363");
user.setMobile("16752652625");
user.setGender(2);
user.setAge(18);
return user;
}
}
第三步:创建一个GlobalBeanFactoryPostProcessor类,实现了BeanFactoryPostProcessor接口文章源自JAVA秀-https://www.javaxiu.com/19883.html
@Component
public class GlobalBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
System.out.println("Execute postProcessBeanFactory.");
//除了xml配置,@Service外,这里是第三种注册bean信息的方式,也就是代码中做注册
BeanDefinitionRegistry bdr = (BeanDefinitionRegistry)beanFactory;
GenericBeanDefinition gbd = new GenericBeanDefinition();
gbd.setBeanClass(UserServiceImpl.class);
gbd.setScope(BeanDefinition.SCOPE_SINGLETON);
gbd.setAutowireCandidate(true);
bdr.registerBeanDefinition("userService", gbd);
}
}
第四步:配置applicationContext.xml文件内容:文章源自JAVA秀-https://www.javaxiu.com/19883.html
<context:component-scan base-package="com.minesoft.tutorial" />
第五步:最后我们运行下面的代码文章源自JAVA秀-https://www.javaxiu.com/19883.html
ClassPathXmlApplicationContext cac = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
UserService userService = cac.getBean(UserService.class);
User user = userService.findUserById(100L);
System.out.println(JSONObject.toJSONString(user));
运行完成上面的代码,我们会发现一个奇怪的事实,就是我们的UserServiceImpl这个bean,既不需要在applicationContext.xml文件中配置,也不需要加上@Service注解,居然也能被spring创建并管理起来,能够正常的使用。其实这种使用方式并不奇怪,只不过我们不常用而已,这种用法正是BeanFactoryPostProcessor接口的常用用法。文章源自JAVA秀-https://www.javaxiu.com/19883.html
总结:从上面我们看到了除了xml配置,和@Service注解之外的第三种注册bean信息的方式,也就是通过实现BeanFactoryPostProcessor接口,在代码中动态的去注册bean信息。那么可能有同学好奇了,前面的两种和这种本质上有啥区别呢?答案是本质上无任何区别。前两种方式最终底层也是执行了第三步的postProcessBeanFactory方法的那段代码,即将bean描述信息注册到beanfactory中去。至于这个解析过程,后面我们会详细的提到。本章节我们先了解这些基础的功能用法。文章源自JAVA秀-https://www.javaxiu.com/19883.html
3. BeanPostProcessor接口和BeanFactoryPostProcessor接口的区别
首先BeanFactory是一个spring的容器,也就是一个容器级别的对象,这个容器对象里面管理着多个bean对象。基于这一点,我们看看下面的二者的不同。文章源自JAVA秀-https://www.javaxiu.com/19883.html
一、二者的量级就不一样,从名称上就能分辨。BeanFactoryPostProcessor接口作用于BeanFactory对象的初始化过程,而BeanPostProcessor接口只能作用Bean对象的初始化过程。一个用于拦截或者介入容器级对象(即BeanFactory对象)的初始化过程;一个用于拦截或者介入bean对象的初始化过程。文章源自JAVA秀-https://www.javaxiu.com/19883.html
二、一个BeanFactoryPostProcessor接口的实现类在spring容器的启动过程中,一般只会被调用一次;而BeanPostProcessor接口的实现类在spring容器的启动过程中,一般会被调用N次(N与这个spring容器所创建和管理的Bean对象一样)。文章源自JAVA秀-https://www.javaxiu.com/19883.html
文章源自JAVA秀-https://www.javaxiu.com/19883.html
更多知识请关注公众号文章源自JAVA秀-https://www.javaxiu.com/19883.html

评论