通过spring容器获取一个类的实例的spring容器接口的,spring获取bean工具类
目录
1.感知界面2。BeanFactoryAware3。天津项目实践
00-1010朋友们都知道,Spring容器最大的特点就是所有的Bean都不知道Spring容器的存在,所以我们常说理论上你可以无缝地把Spring容器切换到其他容器(然而在现实世界中,我们实际上并没有这样的选择。除了弹簧容器还有什么更好用的吗?)。
当然,这只是一个理论。在实际开发中,我们经常会用到Spring容器提供的很多资源,比如容器中的配置,容器中的Bean等等。在这种情况下,需要Spring容器中的bean真正实现Spring容器的存在,那么一个bean如何实现Spring容器的存在呢?
它依赖于Spring容器提供的各种感知接口。
/* * * amarkersuperinterface indicating thatabeaniseligibletobenotifiedbythe * springcontainerofaspecialframeworkobject through a callback-style method。* actualmethodsignature是由individualidualsubidual确定的,但应该*通常是consistofjustonevoid-returning methodthatacceptsasasingleargument。* * pnotetahmerelyimplementing { @ link aware }提供无默认功能。*而是显式处理mustbedone,例如* { @ link org . spring framework . beans . factory . config . beanpostprocessor }。* refer to { @ link org . spring framework . context . support . applicationcontextawareprocessor } * for anxemplofprocessingspecific { @ code * Aware } interface callbacks。* * @ AuthorChrisTeams * @ AuthorJuergenhoeller * @ sinc 3.1 */public interface aware { }从这个接口的注释中,我们也大致可以看出这个接口的子类主要提供了一些只有一个参数的set方法,通过这些方法Spring容器可以感知到一些东西。
Aware有很多实现。一般来说,有以下几种情况:
每个意识到的角色如下:
ApplicationEventPublisherAware:实现该接口的对象可以获得事件发布的能力。ServletContextAware:实现这个接口的对象可以获取ServletContext对象。MessageSourceAware:实现此接口的对象可以获取MessageSource对象。MessageSource支持多个消息源,主要用于国际化。ResourceLoaderAware:实现这个接口的对象可以获得一个ResourceLoader,Spring ResourceLoader为我们提供了一个统一的getResource()方法,通过资源路径检索外部资源,比如文本文件、XML文件、属性文件或者图片文件。ApplicationUpware:实现这个接口的对象可以获得一个ApplicationStartup对象,这是Spring 5.3中相对较新新引入的。通过ApplicationStartup,您可以标记应用程序启动期间的步骤,并收集有关执行上下文或其处理时间的数据。Publisherware:实现这个连接的对象可以获得一个NotificationPublisherAware对象,通过它可以发送通知。EnvironmentAware:实现这个接口的对象可以获得一个环境对象,容器的环境信息可以通过Environment获得。BeanFactoryAware:实现这个接口的对象可以获得一个BeanFactory对象,Bean查询可以通过beanfactory完成。ImportAware:实现这个接口的对象可以获得一个Annota。
tionMetadata 对象,ImportAware 接口是需要和 @Import 注解一起使用的。在 @Import 作为元注解使用时,通过 @Import 导入的配置类如果实现了 ImportAware 接口就可以获取到导入该配置类接口的数据配置。EmbeddedValueResolverAware:实现该接口的对象可以获取到一个 StringValueResolver 对象,通过 StringValueResolver 对象,可以读取到 Spring 容器中的 properties 配置的值(YAML 配置也可以)。ServletConfigAware:实现该接口的对象可以获取到一个 ServletConfig 对象,不过这个似乎没什么用,我们很少自己去配置 ServletConfig。LoadTimeWeaverAware:实现该接口的对象可以获取到一个 LoadTimeWeaver 对象,通过该对象可以获取加载 Spring Bean 时织入的第三方模块,如 AspectJ 等。BeanClassLoaderAware:实现该接口的对象可以获取到一个 ClassLoader 对象,ClassLoader 能干嘛不需要我多说了吧。BeanNameAware:实现该接口的对象可以获取到一个当前 Bean 的名称。ApplicationContextAware:实现该接口的对象可以获取到一个 ApplicationContext 对象,通过 ApplicationContext 可以获取容器中的 Bean、环境等信息。这是 Spring 中提供的一堆 Aware。
接下来松哥随便写个例子大家来看下 Aware 的用法。
2. BeanFactoryAware
实现该接口的对象可以获取到一个 BeanFactory 对象,通过 BeanFactory 可以完成 Bean 的查询等操作。这算是一个比较常见的 Aware 了,我们一起来看下。
这里为了省事,我就在 Spring Boot 中来和大家演示。
首先我们来定义一个简单的 UserService:
@Servicepublic class UserService { public void hello() { System.out.println("hello javaboy!"); }}
然后提供一个工具类:
@Componentpublic class BeanUtils implements BeanFactoryAware { private static BeanFactory beanFactory = null; @Override public void setBeanFactory(BeanFactory beanFactory) throws BeansException { BeanUtils.beanFactory = beanFactory; } public static <T> T getBean(String beanName) { return (T) beanFactory.getBean(beanName); }}
有了这个工具类,接下来我们就可以在一个非 Spring 管理的 Bean 中,随时随地的查询 Bean 了,像下面这样:
UserService userService = BeanUtils.getBean("userService");userService.hello();
3. TienChin 项目实践
为什么会有今天这篇文章呢?主要是在松哥最近做的 TienChin 项目中,有一个地方涉及到这块知识点了,但是有的小伙伴不熟悉,因此就拎出来和大家梳理下。
在 TienChin 项目中,在记录日志的时候,因为日志是一个延迟任务,所以提前准备好了相关的 Bean 已经注册到 Spring 容器中了,像下面这样:
@Configurationpublic class ThreadPoolConfig { /** * 执行周期性或定时任务 */ @Bean(name = "scheduledExecutorService") protected ScheduledExecutorService scheduledExecutorService() { return new ScheduledThreadPoolExecutor(corePoolSize, new BasicThreadFactory.Builder().namingPattern("schedule-pool-%d").daemon(true).build(), new ThreadPoolExecutor.CallerRunsPolicy()) { @Override protected void afterExecute(Runnable r, Throwable t) { super.afterExecute(r, t); Threads.printException(r, t); } }; }}@Componentpublic final class SpringUtils implements BeanFactoryPostProcessor, ApplicationContextAware { /** * Spring应用上下文环境 */ private static ConfigurableListableBeanFactory beanFactory; private static ApplicationContext applicationContext; @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { SpringUtils.beanFactory = beanFactory; } @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { SpringUtils.applicationContext = applicationContext; } /** * 获取对象 * * @param name * @return Object 一个以所给名字注册的bean的实例 * @throws org.springframework.beans.BeansException */ @SuppressWarnings("unchecked") public static <T> T getBean(String name) throws BeansException { return (T) beanFactory.getBean(name); } /** * 获取类型为requiredType的对象 * * @param clz * @return * @throws org.springframework.beans.BeansException */ public static <T> T getBean(Class<T> clz) throws BeansException { T result = (T) beanFactory.getBean(clz); return result; }}
而写日志的异步任务工具类,并非一个容器,所以要通过这个工具类获取相应的 Bean,如下:
public class AsyncManager { /** * 操作延迟10毫秒 */ private final int OPERATE_DELAY_TIME = 10; /** * 异步操作任务调度线程池 */ private ScheduledExecutorService executor = SpringUtils.getBean("scheduledExecutorService"); /** * 单例模式 */ private AsyncManager() { } private static AsyncManager me = new AsyncManager(); public static AsyncManager me() { return me; } /** * 执行任务 * * @param task 任务 */ public void execute(TimerTask task) { executor.schedule(task, OPERATE_DELAY_TIME, TimeUnit.MILLISECONDS); }}
有了 SpringUtils 我们就可以在一个非 Spring 容器所管理的 Bean 中,获取到 Spring 容器中的 Bean 了。
到此这篇关于Spring通过工具类实现获取容器中的Bean的文章就介绍到这了,更多相关Spring获取Bean内容请搜索盛行IT以前的文章或继续浏览下面的相关文章希望大家以后多多支持盛行IT!
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。