大家都知道,項目啟動的時候,spring讀取xml文件,將配置的bean 或者 注解下的controller service dao全部實例化。然后注入到代碼里去使用。那么我們怎么自己去獲取某個實例化的bean呢。自己new是沒用的。
舉個場景,
假設我寫了一個類
public class A{
@Resource
private static ADao aDao;
static{
aDao.select();
}
public static void getA(){
...
}
}
當 別的類里調用A.getA()的時候,調用的是靜態方法,A並不會實例化,只是初始化,也就是說aDao-null;
可能會覺得我設定這個A類很奇葩,但是有的場景就是這樣,為了提高性能,我只允許查庫一次,以后讀取內存。(不放到redis為了安全),所以就要用只會第一次初始化才會被執行的靜態代碼塊。
這個時候我就需要自己去獲取aDao了。
那么怎么獲取呢?
首先我們要知道幾個問題
1, aDao已經實例化了,只是在spring容器中,還不知道怎么去取。
2,如果用的mybatis的接口式編程,那么aDao只是一個接口,他的實現類是MapperFactoryBean,並不是本身,
<bean id="aDap" class=" .../.../aDao"/>這種寫法是錯誤的。
3, ApplicationContext context=new ClassPathXmlApplicationContext("spring-config.xml");
context.getBean("BeanName");
這種做法是平常測試的時候,在不啟動spring的時候的一種加載配置文件實例化bean的方法。
在一個正常啟動的項目中,這樣做是不對的,會使spring重新實例化,重新建立數據庫連接池。這相當於重啟一個正在運行的項目,是很嚴重的。
所以我們要用spring給我們提供的接口去搞。
方法一:實現BeanFactoryAware接口
代碼如下:
@Service
public class BeanUtils implements BeanFactoryAware {
// Spring的bean工廠
private static BeanFactory beanFactory;
@Override
public void setBeanFactory(BeanFactory factory) throws BeansException {
beanFactory=factory;
}
public static<T> T getBean(String beanName){
return (T) beanFactory.getBean(beanName);
}
}
這個類的意思大體這么幾個
1,實現BeanFactoryAware接口,這個接口可以讓我們在項目啟動后獲取bena工廠的實例,從而隨心所欲的獲取我們想要的bean實例。
2,setBeanFactory()方法是用的spring的依賴注入,set方法是三種注入方式之一。這樣實例才會注入到該類里。
既然要注入,那么我們必須設置BeanUtils這個類也要在項目啟動的時候被spring實例化,我這里是采用注解的方式@service來實現。
3,靜態getBean方法,這里方法必須是靜態的,因為你如果自己去new這個BeanUtils類的話,beanFactory是不會被注入進去的。
方法二,非常簡單的一種用法。
ContextLoaderListener.getCurrentWebApplicationContext().getBean ("beanName");
使用 上下文監聽器去獲取上下文,然后獲取bean,這個方法細心的同學應該能看到,這是上面我講的一種錯誤用法的改變。3, ApplicationContext context=new ClassPathXmlApplicationContext("spring-config.xml");,用一句話概述就是,new是不管用的,從容器中拿出來才是正道。
關於ContextLoaderListener這個監聽器就不多說了。
這里只列出兩種,還有幾種方式,也可以獲取。
如果哪里解釋的不對,希望大神指點下小弟,畢竟自己摸索,難免會出錯。