控制反轉(InversionofControl,縮寫為IoC)
簡單來說就是當自己需要一個對象的時候不需要自己手動去new一個,而是由其他容器來幫你提供;Spring裡面就是IOC容器。
例如:
在Spring裡面經常需要在Service這個裝配一個Dao,一般是使用@Autowired註解:類似如下
public Class ServiceImpl{ @Autowired Dao dao; public void getData(){ dao.getData(); }在這裡未初始化Dao直接使用是會報出空指針異常的,那麼在Spring裡面的做法就是通過反射來將需要的類幫你加載進來。
下面是一個例子模擬了Spring的DI和IOC
首先寫兩個註解模擬Spring的註解:
Entity註解代表的是Spring的@Service@Target(ElementType.TYPE) // 類@Retention(RetentionPolicy.RUNTIME)public @interface Entity {}代表的是Spring裡面的@Autowrid@Target(ElementType.FIELD) //描述方法的@Retention(RetentionPolicy.RUNTIME) // 僅運行時保留public @interface Resources {}當註解建立完成之後再建立兩個類:
Rain類代表的是需要從其他地方獲取天氣數據(數據庫或者服務器)
public class Rain { public void rain(){ System.out.println("正在下雨"); // 為了方便直接寫了}}Weather類代表的是獲取到的天氣數據
@Entitypublic class Weather { @Resources Rain rain; // 這裡在後面通過反射直接注入rain public void weather_rain() { rain.rain(); }下面是通過反射來直接注入:
首先遍歷指定的包名:這一步先省略,
首先是建立一個List模擬Spring的bean容器,即將已經裝初始化好的帶有Entity註解的類全部初始化
public class Weather_reflec {List<Object> objectList ;// 模擬Spring容器public Weather_reflec() {objectList= new ArrayList<Object>();}// 在這裡其實最好的做法是先找出帶有註解的類,判斷帶有Entity註解再傳入。但是為了方便直接省略了public void get_ref(Object object) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {Class<?> clazz =object.getClass();if(clazz.isAnnotationPresent(Entity.class)){//判斷是否帶有Entity註解Field[] fields =clazz.getDeclaredFields();//獲取其變量for (Field field :fields){if(field.isAnnotationPresent(Resources.class)){//判斷是否需要注入Class<?> rainClass=Class.forName(field.getType().getName(),false,Thread.currentThread().getContextClassLoader());// 這裡先將Rain類加載field.set(object,rainClass.newInstance());//賦給rainobjectList.add(object);//最後將已將賦值後的Weather保存進容器}}}}public List<Object> returnList(){return objectList;//返回容器方便以後使用}最後也就是模擬Controller裡面直接使用的
public class WeatherPrediction {public static void main(String args[]) throws ClassNotFoundException, NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException {WeatherPrediction weatherPrediction =new WeatherPrediction();Weather weather =(Weather)weatherPrediction.springDo();weather.weather_rain();// 這裡如果是普通調用會報空指針異常,而容器卻為其將rain這個變量賦值了,所以可以正常輸出}/* 模擬Spring啟動過程,這一步其實可以單獨寫一個類,這一步是容器該做的,而我們並不需要去管*/public Object springDo() throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {Weather_reflec weather_reflec =new Weather_reflec();// 啟動的時候就需要加載的Weather weather =new Weather();//掃描類註解後new操作然後進行下一步weather_reflec.get_ref(weather);// 將其類裡面的變量進行new操作並放入容器Object object =weather_reflec.returnList().get(0);return object;}運行後輸出:正在下雨在WeatherPrediction裡面並沒有對Rain進行一個new操作但是卻可以使用,這應該是最簡單的一個模擬Spring的IOC例子了,當然Spring的IOC容器比這個強大太多了,比如需要考慮線程安全,以及各種的細節問題
總結
以上就是本文關於簡單實現Spring的IOC原理詳解的全部內容,希望對大家有所幫助。感興趣的朋友可以繼續參閱本站:
Spring IOC原理詳解
簡單理解Spring之IOC和AOP及代碼示例
如有不足之處,歡迎留言指出。感謝朋友們對本站的支持!