日本免费高清视频-国产福利视频导航-黄色在线播放国产-天天操天天操天天操天天操|www.shdianci.com

學(xué)無先后,達(dá)者為師

網(wǎng)站首頁 編程語言 正文

SpringBoot中的SmartInitializingSingleton接口的使用

作者:神筆碼靚 更新時間: 2022-07-13 編程語言

一、說明

SmartInitializingSingleton 接口的 afterSingletonsInstantiated()方法類似bean實例化執(zhí)行后的回調(diào)函數(shù)。
afterSingletonsInstantiated 會在spring 容器基本啟動完成后執(zhí)行。此時所有的單列bean都已初始化完成。實現(xiàn)了SmartInitializingSingleton 接口的類
可以在afterSingletonsInstantiated 中做一些回調(diào)操作。

二、XXL-JOB 中SmartInitializingSingleton 的使用

xxl-job 是一個輕量級的分布式任務(wù)調(diào)度框架,通過一個中心式的調(diào)度平臺,調(diào)度多個執(zhí)行器執(zhí)行任務(wù),而且監(jiān)控界面就集成在調(diào)度中心,界面又簡潔。

xxl-job中, XxlJobSpringExecutor,XxlJobSimpleExecutor 繼承自 XxlJobExecutor 同時也實現(xiàn)了 SmartInitializingSingleton 接口。
XxlJobSpringExecutor 在 afterSingletonsInstantiated() 方法中,完成了提取 @XxlJob 注解標(biāo)注的方法,用于后續(xù)任務(wù)的執(zhí)行。調(diào)用父類方法中的start() 方法,初始化netty服務(wù)器。

public class XxlJobSpringExecutor extends XxlJobExecutor implements ApplicationContextAware, SmartInitializingSingleton, DisposableBean {
    private static final Logger logger = LoggerFactory.getLogger(XxlJobSpringExecutor.class);


    // start
    @Override
    public void afterSingletonsInstantiated() {

        // init JobHandler Repository
        /*initJobHandlerRepository(applicationContext);*/

        // init JobHandler Repository (for method)
        initJobHandlerMethodRepository(applicationContext);

        // refresh GlueFactory
        GlueFactory.refreshInstance(1);

        // super start
        try {
            super.start();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
	/// 其他代碼 省略
}

父類中的start() 方法:initEmbedServer 用于初始化netty服務(wù)。


    // ---------------------- start + stop ----------------------
    public void start() throws Exception {

        // init logpath
        XxlJobFileAppender.initLogPath(logPath);

        // init invoker, admin-client
        initAdminBizList(adminAddresses, accessToken);


        // init JobLogFileCleanThread
        JobLogFileCleanThread.getInstance().start(logRetentionDays);

        // init TriggerCallbackThread
        TriggerCallbackThread.getInstance().start();

        // init executor-server 初始化netty 服務(wù)
        initEmbedServer(address, ip, port, appname, accessToken);
    }

獲取容器中被@XxlJob 注解標(biāo)注的方法的實現(xiàn)方法:


    private void initJobHandlerMethodRepository(ApplicationContext applicationContext) {
        if (applicationContext == null) {
            return;
        }
        // init job handler from method
        String[] beanDefinitionNames = applicationContext.getBeanNamesForType(Object.class, false, true);
        for (String beanDefinitionName : beanDefinitionNames) {
            Object bean = applicationContext.getBean(beanDefinitionName);

            Map<Method, XxlJob> annotatedMethods = null;   // referred to :org.springframework.context.event.EventListenerMethodProcessor.processBean
            try {
                annotatedMethods = MethodIntrospector.selectMethods(bean.getClass(),
                        new MethodIntrospector.MetadataLookup<XxlJob>() {
                            @Override
                            public XxlJob inspect(Method method) {
                                return AnnotatedElementUtils.findMergedAnnotation(method, XxlJob.class);
                            }
                        });
            } catch (Throwable ex) {
                logger.error("xxl-job method-jobhandler resolve error for bean[" + beanDefinitionName + "].", ex);
            }
            if (annotatedMethods==null || annotatedMethods.isEmpty()) {
                continue;
            }

            for (Map.Entry<Method, XxlJob> methodXxlJobEntry : annotatedMethods.entrySet()) {
                Method executeMethod = methodXxlJobEntry.getKey();
                XxlJob xxlJob = methodXxlJobEntry.getValue();
                // regist
                registJobHandler(xxlJob, bean, executeMethod);
            }
        }
    }

使用時和其他框架差不多,在@Configuraton 修飾的配置類中返回一個示例化的bean即可。


@Configuration
public class XxlJobConfig {
    @Bean
    public XxlJobSpringExecutor xxlJobExecutor() {
        logger.info(">>>>>>>>>>> xxl-job config init.");
        XxlJobSpringExecutor xxlJobSpringExecutor = new XxlJobSpringExecutor();
        xxlJobSpringExecutor.setAdminAddresses(adminAddresses);
        xxlJobSpringExecutor.setAppname(appname);
        xxlJobSpringExecutor.setAddress(address);
        xxlJobSpringExecutor.setIp(ip);
        xxlJobSpringExecutor.setPort(port);
        xxlJobSpringExecutor.setAccessToken(accessToken);
        xxlJobSpringExecutor.setLogPath(logPath);
        xxlJobSpringExecutor.setLogRetentionDays(logRetentionDays);

        return xxlJobSpringExecutor;
    }
}

三、spring 容器中 SmartInitializingSingleton 的使用

EventListenerMethodProcessor也實現(xiàn)了 SmartInitializingSingleton 接口,主要用于完成@EventListener注解方式的事件監(jiān)聽。
在afterSingletonsInstantiated() 方法中處理邏輯與xxl-job 中的類似,都是用于篩選實例中被指定注解修飾的方法。

public class EventListenerMethodProcessor
		implements SmartInitializingSingleton, ApplicationContextAware, BeanFactoryPostProcessor {

	
	@Override
	public void afterSingletonsInstantiated() {
		ConfigurableListableBeanFactory beanFactory = this.beanFactory;
		Assert.state(this.beanFactory != null, "No ConfigurableListableBeanFactory set");
		String[] beanNames = beanFactory.getBeanNamesForType(Object.class);
		for (String beanName : beanNames) {
			if (!ScopedProxyUtils.isScopedTarget(beanName)) {
				Class<?> type = null;
				try {
					type = AutoProxyUtils.determineTargetClass(beanFactory, beanName);
				}
				catch (Throwable ex) {
					// An unresolvable bean type, probably from a lazy bean - let's ignore it.
					if (logger.isDebugEnabled()) {
						logger.debug("Could not resolve target class for bean with name '" + beanName + "'", ex);
					}
				}
				if (type != null) {
					if (ScopedObject.class.isAssignableFrom(type)) {
						try {
							Class<?> targetClass = AutoProxyUtils.determineTargetClass(
									beanFactory, ScopedProxyUtils.getTargetBeanName(beanName));
							if (targetClass != null) {
								type = targetClass;
							}
						}
						catch (Throwable ex) {
							// An invalid scoped proxy arrangement - let's ignore it.
							if (logger.isDebugEnabled()) {
								logger.debug("Could not resolve target bean for scoped proxy '" + beanName + "'", ex);
							}
						}
					}
					try {
						processBean(beanName, type);
					}
					catch (Throwable ex) {
						throw new BeanInitializationException("Failed to process @EventListener " +
								"annotation on bean with name '" + beanName + "'", ex);
					}
				}
			}
		}
	}

}

寫在最后

以上兩個使用的方式都是在spring容器 單列被加載完成后,處理一些自定義的邏輯。EventListenerMethodProcessor主要用于篩選出被@EventListener
注解的方法,在后續(xù)的使用中 通過 發(fā)布-訂閱模式,實現(xiàn)事件的監(jiān)聽。

XxlJobSpringExecutor 主要用于篩選出被@XxlJob 注解標(biāo)注的方法,用于后續(xù)任務(wù)的啟動和停止。

原文鏈接:https://blog.csdn.net/daxues_/article/details/125750267

欄目分類
最近更新