掃二維碼與項(xiàng)目經(jīng)理溝通
我們?cè)谖⑿派?4小時(shí)期待你的聲音
解答本文疑問/技術(shù)咨詢/運(yùn)營(yíng)咨詢/技術(shù)建議/互聯(lián)網(wǎng)交流
當(dāng)然這只是一個(gè)理論,在實(shí)際開發(fā)中,我們往往要用到 Spring 容器為我們提供的諸多資源,例如想要獲取到容器中的配置、獲取到容器中的 Bean 等等。在這種情況下,就需要 Spring 容器中的 Bean 真正的意識(shí)到 Spring 容器的存在,才能要到這些東西,那么如何讓一個(gè) Bean 意識(shí)到 Spring 容器的存在呢?

這就依賴于 Spring 容器給我們提供的各種 Aware 接口了。
/**
* A marker superinterface indicating that a bean is eligible to be notified by the
* Spring container of a particular framework object through a callback-style method.
* The actual method signature is determined by individual subinterfaces but should
* typically consist of just one void-returning method that accepts a single argument.
*
*Note that merely implementing {@link Aware} provides no default functionality.
* Rather, processing must be done explicitly, for example in a
* {@link org.springframework.beans.factory.config.BeanPostProcessor}.
* Refer to {@link org.springframework.context.support.ApplicationContextAwareProcessor}
* for an example of processing specific {@code *Aware} interface callbacks.
*
* @author Chris Beams
* @author Juergen Hoeller
* @since 3.1
*/
public interface Aware {
}
從這個(gè)接口的注釋中,我們也能大概看出來,這個(gè)接口的子類,主要是提供了一些只有一個(gè)參數(shù)的 set 方法,通過這些方法可以讓 Spring 容器感知到某一件事情。
Aware 的實(shí)現(xiàn)有很多,大的方向來說主要有如下一些:
每一個(gè) Aware 的作用如下:
這是 Spring 中提供的一堆 Aware。
接下來松哥隨便寫個(gè)例子大家來看下 Aware 的用法。
實(shí)現(xiàn)該接口的對(duì)象可以獲取到一個(gè) BeanFactory 對(duì)象,通過 BeanFactory 可以完成 Bean 的查詢等操作。這算是一個(gè)比較常見的 Aware 了,我們一起來看下。
這里為了省事,我就在 Spring Boot 中來和大家演示。
首先我們來定義一個(gè)簡(jiǎn)單的 UserService:
@Service
public class UserService {
public void hello() {
System.out.println("hello javaboy!");
}
}
然后提供一個(gè)工具類:
@Component
public class BeanUtils implements BeanFactoryAware {
private static BeanFactory beanFactory = null;
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
BeanUtils.beanFactory = beanFactory;
}
public staticT getBean(String beanName) {
return (T) beanFactory.getBean(beanName);
}
}
有了這個(gè)工具類,接下來我們就可以在一個(gè)非 Spring 管理的 Bean 中,隨時(shí)隨地的查詢 Bean 了,像下面這樣:
UserService userService = BeanUtils.getBean("userService");
userService.hello();為什么會(huì)有今天這篇文章呢?主要是在松哥最近做的 TienChin 項(xiàng)目中,有一個(gè)地方涉及到這塊知識(shí)點(diǎn)了,但是有的小伙伴不熟悉,因此就拎出來和大家梳理下。
在 TienChin 項(xiàng)目中,在記錄日志的時(shí)候,因?yàn)槿罩臼且粋€(gè)延遲任務(wù),所以提前準(zhǔn)備好了相關(guān)的 Bean 已經(jīng)注冊(cè)到 Spring 容器中了,像下面這樣:
@Configuration
public class ThreadPoolConfig {
/**
* 執(zhí)行周期性或定時(shí)任務(wù)
*/
@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);
}
};
}
}
@Component
public final class SpringUtils implements BeanFactoryPostProcessor, ApplicationContextAware {
/**
* Spring應(yīng)用上下文環(huán)境
*/
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;
}
/**
* 獲取對(duì)象
*
* @param name
* @return Object 一個(gè)以所給名字注冊(cè)的bean的實(shí)例
* @throws org.springframework.beans.BeansException
*/
@SuppressWarnings("unchecked")
public staticT getBean(String name) throws BeansException {
return (T) beanFactory.getBean(name);
}
/**
* 獲取類型為requiredType的對(duì)象
*
* @param clz
* @return
* @throws org.springframework.beans.BeansException
*/
public staticT getBean(Class clz) throws BeansException {
T result = (T) beanFactory.getBean(clz);
return result;
}
}
而寫日志的異步任務(wù)工具類,并非一個(gè)容器,所以要通過這個(gè)工具類獲取相應(yīng)的 Bean,如下:
public class AsyncManager {
/**
* 操作延遲10毫秒
*/
private final int OPERATE_DELAY_TIME = 10;
/**
* 異步操作任務(wù)調(diào)度線程池
*/
private ScheduledExecutorService executor = SpringUtils.getBean("scheduledExecutorService");
/**
* 單例模式
*/
private AsyncManager() {
}
private static AsyncManager me = new AsyncManager();
public static AsyncManager me() {
return me;
}
/**
* 執(zhí)行任務(wù)
*
* @param task 任務(wù)
*/
public void execute(TimerTask task) {
executor.schedule(task, OPERATE_DELAY_TIME, TimeUnit.MILLISECONDS);
}
}有了 SpringUtils 我們就可以在一個(gè)非 Spring 容器所管理的 Bean 中,獲取到 Spring 容器中的 Bean 了。

我們?cè)谖⑿派?4小時(shí)期待你的聲音
解答本文疑問/技術(shù)咨詢/運(yùn)營(yíng)咨詢/技術(shù)建議/互聯(lián)網(wǎng)交流