原理
@Configuration
从Spring3.0,@Configuration用于定义配置类,可替换xml配置文件,被注解的类内部包含有一个或多个被@Bean注解的方法,这些方法将会被AnnotationConfigApplicationContext或AnnotationConfigWebApplicationContext类进行扫描,并用于构建bean定义,初始化Spring容器。
注意:
@Configuration注解的配置类有如下要求:
@Configuration不可以是final类型;
@Configuration不可以是匿名类;
嵌套的configuration必须是静态类。
ApplicationContextAware
在我们需要使用ApplicationContext的服务中实现ApplicationContextAware接口,系统启动时就可以自动给我们的服务注入applicationContext对象,我们就可以获取到ApplicationContext里的所有信息了。
SmartInitializingSingleton
当所有单例 bean都初始化完成以后,容器会回调SmartInitializingSingleton接口的 afterSingletonsInstantiated方法。以此实现在所有单例 bean 创建完成之后,可以在该回调中做一些事情。
实现
1.实现afterSingletonsInstantiated
@Override
public void afterSingletonsInstantiated() {
// 1.获取所有使用RocketMQMessageListener注解的bean
Map<String, Object> beans = this.applicationContext.getBeansWithAnnotation(ZMQMessageListener.class);
if (Objects.nonNull(beans)) {
// 2.注册bean(RocketMqListener容器)
beans.forEach(this::registerContainer);
}
}
2.注册容器
/**
* Register the listener to container
*
* @param beanName
* @param bean
*/
private void registerContainer(String beanName, Object bean) {
Class<?> clazz = AopProxyUtils.ultimateTargetClass(bean);
// 检查是否实现了RocketMQListener的方法
if (!ZMQListener.class.isAssignableFrom(bean.getClass())) {
throw new IllegalStateException(clazz + " is not instance of " + ZMQListener.class.getName());
}
ZMQMessageListener annotation = clazz.getAnnotation(ZMQMessageListener.class);
String containerBeanName = String.format("%s_%s", DefaultRocketMQListenerContainer.class.getName(),
counter.incrementAndGet());
/**
* Generic ApplicationContext 持有一个DefaultListableBeanFactory实例,并且没有假设一个特定的bean definition 的format。
* 实现了BeanDefinitionRegistry接口以允许配置任何bean definition reader(也可以不是XmlBeanDefinitionReader)。
*/
GenericApplicationContext genericApplicationContext = (GenericApplicationContext) applicationContext;
// 注册bean
// 低版本的spring版本智能注册BeanDefinition,高版本的可以用registerBean方法直接注册bean
genericApplicationContext.registerBeanDefinition(containerBeanName,
createRocketMQListenerContainer(containerBeanName, bean, annotation).getBeanDefinition());
// 注册完成