当前位置: 首页 > 科技观察

工具类如何获取Spring容器中的bean?_0

时间:2023-03-19 22:51:01 科技观察

1。了解接口的朋友都知道,Spring容器最大的特点就是所有的bean都不知道Spring容器的存在,所以我们常说理论上可以无缝切换Spring容器到其他容器(然而在现实世界中,我们实际上没有这样的选择,除了Spring容器,还有更好的吗?)。当然,这只是一种理论。在实际开发中,我们经常需要用到Spring容器提供的很多资源,比如获取容器中的配置,获取容器中的bean等等。在这种情况下,Spring容器中的Bean需要真正感知到Spring容器的存在,才能获取到这些东西,那么如何让一个Bean感知到Spring容器的存在呢?这取决于Spring容器提供的各种Aware接口。/***一个标记超接口,指示一个bean有资格通过回调样式的方法被特定框架对象的*Spring容器通知。*实际的方法签名由各个子接口决定,但*通常应该只包含一个接受单个参数的返回void的方法。**

请注意,仅实施{@linkAware}不提供默认功能。*相反,处理必须显式完成,例如在*{@linkorg.springframework.beans.factory.config.BeanPostProcessor}中。*请参阅{@linkorg.springframework.context.support.ApplicationContextAwareProcessor}*以获取处理特定{@code*Aware}接口回调的示例。**@authorChrisBeams*@authorJuergenHoeller*@since3.1*/publicinterfaceAware{}从这个接口的注释中我们也可以大致看出,这个接口的子类主要提供一些只有一个参数的set方法。通过这些方法,可以让Spring容器感知到某个事物。Aware的实现有多种,主要方向如下:各个Aware的作用如下:ApplicationEventPublisherAware:实现该接口的对象可以获得发布事件的能力。ServletContextAware:实现该接口的对象可以获得ServletContext对象。MessageSourceAware:实现该接口的对象可以获得MessageSource对象。MessageSource支持多种消息源,主要用于国际化。ResourceLoaderAware:实现该接口的对象可以获得一个ResourceLoader,SpringResourceLoader为我们提供了统一的getResource()方法,可以通过资源路径获取外部资源,如文本文件、XML文件、属性文件或图片文件等。ApplicationStartupAware:实现该接口的对象可以获得一个ApplicationStartup对象,比较新,是Spring5.3新引入的。通过ApplicationStartup,可以标记应用程序启动过程中的步骤,并收集有关执行上下文或处理时间的数据。NotificationPublisherAware:实现这个连接的对象可以获得一个NotificationPublisher对象,通过它可以发送通知。EnvironmentAware:实现该接口的对象可以获得一个Environment对象,通过该对象可以获得容器的环境信息。BeanFactoryAware:实现该接口的对象可以获得一个BeanFactory对象,通过BeanFactory完成Bean的查询等操作。ImportAware:实现该接口的对象可以获得一个AnnotationMetadata对象。ImportAware接口需要配合@Import注解使用。当使用@Import作为元注解时,如果通过@Import导入的配置类实现了ImportAware接口,则可以获取配置类接口导入的数据配置。EmbeddedValueResolverAware:实现该接口的对象可以获得一个StringValueResolver对象,通过StringValueResolver对象可以读取Spring容器中的properties配置的值(YAML配置也可以)。ServletConfigAware:实现该接口的对象可以获得一个ServletConfig对象,但是这个好像没什么用,我们很少自己配置ServletConfig。LoadTimeWeaverAware:实现该接口的对象可以获得一个LoadTimeWeaver对象,通过该对象可以获取编织成SpringBean的第三方模块,如AspectJ。BeanClassLoaderAware:实现该接口的对象可以获得一个ClassLoader对象。ClassLoader能干什么我就不用多说了。BeanNameAware:实现该接口的对象可以获得当前Bean的名称。ApplicationContextAware:实现该接口的对象可以获得一个ApplicationContext对象,通过该对象可以获得容器中的bean、环境等信息。这是Spring提供的一堆Aware。接下来宋哥随便写个例子给大家看看如何使用Aware。2、实现该接口的BeanFactoryAware对象可以获得一个BeanFactory对象,通过BeanFactory完成Bean查询等操作。这是一个比较常见的Aware,我们来看一下。这里为了省事,我在SpringBoot中给大家演示一下。首先,让我们定义一个简单的UserService:@ServicepublicclassUserService{publicvoidhello(){System.out.println("hellojavaboy!");}}然后提供一个工具类:@ComponentpublicclassBeanUtilsimplementsBeanFactoryAware{privatestaticBeanFactorybeanFactory=null;@OverridepublicvoidsetBeanFactory(BeanFactorybeanFactory)throwsBeansException{BeanUtils.beanFactory=beanFactory;}publicstaticTgetBean(StringbeanName){return(T)beanFactory.getBean(beanName);有了这个工具类,我们就可以随时随地在非Spring管理的Bean中查询Bean了,如下:UserServiceuserService=BeanUtils.getBean("userService");userService.hello();3.为什么今天天津项目实践会有这篇文章?主要是松哥最近做的TienChin项目中,有一个地方和这个知识点相关,但是有些小伙伴不熟悉,所以我拿出来和大家一起整理一下。在TienChin项目中,在打日志的时候,因为打日志是一个延时任务,相关的Bean已经提前准备好,注册到Spring容器中,如下:@ConfigurationpublicclassThreadPoolConfig{/***周期性执行或者定时任务*/@Bean(name="scheduledExecutorService")protectedScheduledExecutorServicescheduledExecutorService(){returnnewScheduledThreadPoolExecutor(corePoolSize,newBasicThreadFactory.Builder().namingPattern("schedule-pool-%d").daemon(true).build(),newThreadPoolExecutor.CallerRunsPolicy()){@OverrideprotectedvoidafterExecute(Runnabler,Throwablet){super.afterExecute(r,t);Threads.printException(r,t);}};}}@ComponentpublicfinalclassSpringUtilsimplementsBeanFactoryPostProcessor,ApplicationContextAware{/***Spring应用上下文*/privatestaticConfigurableListableBeanFactorybeanFactory;私有静态ApplicationContextapplicationContext;@覆盖publicvoidpostProcessBeanFactory(ConfigurableListableBeanFactorybeanFactory)throwsBeansException{SpringUtils.beanFactory=beanFactory;}@OverridepublicvoidsetApplicationContext(ApplicationContextapplicationContext)throwsBeansException{@SpringUtils.applicationContext=beanFactory;Object使用给定名称注册的bean实例*@throwsorg.springframework.beans.BeansException*/@SuppressWarnings("unchecked")publicstaticTgetBean(Stringname)throwsBeansException{return(T)beanFactory.getBean(名字);}/***获取类型为requiredType的对象**@paramclz*@return*@throwsorg.springframework.beans.BeansException*/publicstaticTgetBean(Classclz)throwsBeansException{Tresult=(T)beanFactory.getBean(clz);返回结果;}}写日志的异步任务工具类不是容器,所以需要使用这个工具类来获取相关对应的Bean如下:publicclassAsyncManager{/***操作延迟10毫秒*/privatefinalintOPERATE_DELAY_TIME=10;/***异步操作任务调度线程池*/privateScheduledExecutorServiceexecutor=SpringUtils.getBean("scheduledExecutorService");/***单例模式*/privateAsyncManager(){}privatestaticAsyncManagerme=newAsyncManager();publicstaticAsyncManagerme(){返回我;}/***执行任务**@paramtasktask*/publicvoidexecute(TimerTasktask){executor.schedule(task,OPERATE_DELAY_TIME,TimeUnit.MILLISECONDS);}}通过SpringUtils,我们可以在一个不受Spring容器管理的Bean中获取Spring容器中的Bean