日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

一起写框架-Ioc内核容器的实现-对象的调用-属性注入容器的对象(十)

發(fā)布時(shí)間:2023/11/29 编程问答 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 一起写框架-Ioc内核容器的实现-对象的调用-属性注入容器的对象(十) 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

實(shí)現(xiàn)功能

?

需求:在類的成員屬性使用@Autowirde注解注入容器中的對(duì)象。

?

實(shí)現(xiàn)思路

要實(shí)現(xiàn)這個(gè)功能。我們首先要思考一個(gè)問題:類與類的關(guān)系是在調(diào)用的建立的,還是說在創(chuàng)建對(duì)象的時(shí)候就就將建立了?

?

---我實(shí)現(xiàn)的方案是,在在程序啟動(dòng)后,所有對(duì)象創(chuàng)建后直接就將對(duì)象的屬性和屬性之間的關(guān)系創(chuàng)建了。接下來我就用這個(gè)思路來實(shí)現(xiàn),將根據(jù)@Autowirde建立對(duì)象與對(duì)象之間的關(guān)系。

?

為什么一定要對(duì)象全部創(chuàng)建后再實(shí)現(xiàn)對(duì)象與對(duì)象直接的關(guān)系呢?

這個(gè)是邏輯問題,如果對(duì)象沒有創(chuàng)建完就建立對(duì)象與對(duì)象之間的關(guān)系,人家都還沒有創(chuàng)建,你怎么引用呢?對(duì)吧。所有一定在所有對(duì)象創(chuàng)建完后建立對(duì)象與對(duì)象的關(guān)系。

?

?

實(shí)現(xiàn)步驟

1.Context接口增加一個(gè)方法。用于通過Map的和屬性名對(duì)象或者對(duì)象的類型與屬性的類型對(duì)象,給屬性匹配對(duì)象。定義如代碼的說明

?

1 /** 2 * 根據(jù)類的類型以及設(shè)置的對(duì)象名返回容器對(duì)象 3 * 如果傳入的類型容器中有對(duì)應(yīng)key的對(duì)象,而且返回類型是兼容的,直接返回對(duì)應(yīng)的對(duì)象。 4 * 如果傳入的類型容器中有沒有對(duì)應(yīng)key的對(duì)象,那么判斷傳入的類型是否和容器的對(duì)象的找到唯一配置的。 5 * 如果傳入類型唯一匹配,返回對(duì)象。如果沒有或者配配多個(gè)對(duì)象,都報(bào)一個(gè)RuntimeException異常 6 * @param classType 7 * @return 8 */ 9 Object getObject(Class<?> classType,String key);

?

2.在ContextImpl容器實(shí)現(xiàn)類實(shí)現(xiàn)這個(gè)方法

1 @Override 2 public Object getObject(Class<?> classType, String key) { 3 // 1.判斷是否有對(duì)應(yīng)key的對(duì)象 4 Object object = objects.get(key); 5 // 2.如果有,而且類型也兼容。直接返回該對(duì)象。 6 if (object != null && classType.isAssignableFrom(object.getClass())) { 7 return object; 8 } else { 9 // 3.如果沒有對(duì)應(yīng)key的對(duì)象,那么就在容器里檢索,是否有兼容類型的對(duì)象。 10 Collection<Object> values = objects.values(); 11 Iterator<Object> iterator = values.iterator(); 12 int count = 0; 13 Object currentObject = null; 14 while (iterator.hasNext()) { 15 Object nextObject = iterator.next(); 16 //判斷classType是否是nextObject.getClass()的兼容類型。 17 boolean from = classType.isAssignableFrom(nextObject.getClass()) ; 18 if (from) { 19 //如果發(fā)現(xiàn)有對(duì)象,計(jì)數(shù)加1 20 count++; 21 //并將對(duì)象賦予當(dāng)前對(duì)象 22 currentObject = nextObject; 23 } 24 } 25 // 如果兼容類型的對(duì)象只有一個(gè),返回這個(gè)對(duì)象。如果大于一個(gè),返回null 26 if (count == 1) { 27 return currentObject; 28 } else { 29 //如果發(fā)現(xiàn)一個(gè)類型容器中有多個(gè)異常,拋異常 30 throw new RuntimeException("容器中找不到對(duì)應(yīng)的對(duì)象或者找到的對(duì)象不是唯一的!請(qǐng)確認(rèn)是否一個(gè)接口繼承了多個(gè)類"); 31 } 32 33 } 34 35 }

3.AbstractApplicationContext容器操作類實(shí)現(xiàn)屬性的注入方法 autowired()

?

1 /** 2 * 給對(duì)象的屬性注入關(guān)聯(lián)的對(duì)象 3 * @throws IllegalArgumentException 4 * @throws IllegalAccessException 5 */ 6 private void autowired() throws IllegalArgumentException, IllegalAccessException { 7 // 1.獲得容器 8 Context context = contexts.get(); 9 // 2.獲得容器中的所有對(duì)象。 10 Map<String, Object> objects = context.getObjects(); 11 // 3.獲得容器中所有的對(duì)象值 12 Collection<Object> values = objects.values(); 13 // 4.獲得對(duì)象的迭代器 14 Iterator<Object> iterator = values.iterator(); 15 while (iterator.hasNext()) { 16 Object object = iterator.next(); 17 // 5.獲得對(duì)象的表結(jié)構(gòu) 18 Class<? extends Object> classType = object.getClass(); 19 // 6.獲得字段的結(jié)構(gòu) 20 Field[] fields = classType.getDeclaredFields(); 21 for (int i = 0; i < fields.length; i++) { 22 // autowired獲得注解 23 Autowired autowired = fields[i].getAnnotation(Autowired.class); 24 if (autowired != null) { 25 Class<?> fieldType = fields[i].getType(); 26 String fieldName = fields[i].getName(); 27 // 如果容器里面有對(duì)應(yīng)的對(duì)象 28 Object fieldObject = context.getObject(fieldType, fieldName); 29 // 允許訪問私有方法 30 if (fieldObject != null) { 31 // 屬性是私有的也可以訪問 32 fields[i].setAccessible(true); 33 // 將屬性值賦予這個(gè)對(duì)象的屬性 34 fields[i].set(object, fieldObject); 35 } 36 37 } 38 } 39 } 40 }

?

4. AbstractApplicationContext構(gòu)造方法最后調(diào)用屬性注入方法autowired,注意標(biāo)紅處

?

1 public AbstractApplicationContext(Class<?> classType) { 2 try { 3 // 判斷配置類是否有Configuration注解 4 Configuration annotation = classType.getDeclaredAnnotation(Configuration.class); 5 if (annotation != null) { 6 // 獲得組件掃描注解 7 ComponentScan componentScan = classType.getDeclaredAnnotation(ComponentScan.class); 8 // 獲得包名 9 this.basePackage = componentScan.basePackages(); 10 // 根據(jù)包名獲得類全限制名 11 // Set<String> classNames = 12 // PackageUtils.getClassName(this.basePackage[0], true); 13 // 將掃描一個(gè)包,修改為多個(gè)包 14 Set<String> classNames = PackageUtils.getClassNames(this.basePackage, true); 15 // 通過類名創(chuàng)建對(duì)象 16 Iterator<String> iteratorClassName = classNames.iterator(); 17 while (iteratorClassName.hasNext()) { 18 19 String className = iteratorClassName.next(); 20 // System.out.println(className); 21 22 // 通過類全名創(chuàng)建對(duì)象 23 Class<?> objectClassType = Class.forName(className); 24 /* 25 * 判斷如果類權(quán)限名對(duì)應(yīng)的不是接口,并且包含有@Component|@Controller|@Service| 26 * 27 * @Repository 才可以創(chuàng)建對(duì)象 28 */ 29 if (this.isComponent(objectClassType)) { 30 Object instance = objectClassType.newInstance(); 31 // 修改為,默認(rèn)對(duì)象支持首字符小寫 32 String objectName = null; 33 // 獲得組件注解的name屬性值 34 String componentName = this.getComponentOfName(objectClassType); 35 36 if (componentName == null) { 37 // 如果組件注解的name屬性沒有值,使用默認(rèn)命名對(duì)象 38 objectName = NamingUtils.firstCharToLower(instance.getClass().getSimpleName()); 39 } else { 40 // 如果組件注解的name屬性有值,使用自定義命名對(duì)象 41 objectName = componentName; 42 } 43 this.getContext().addObject(objectName, instance); 44 } 45 46 } 47 } 48 //1.注入對(duì)象到屬性中。 49 autowired(); 50 } catch (InstantiationException e) { 51 e.printStackTrace(); 52 } catch (IllegalAccessException e) { 53 e.printStackTrace(); 54 } catch (ClassNotFoundException e) { 55 e.printStackTrace(); 56 } 57 58 }

?

?測試代碼

測試類目錄結(jié)構(gòu)

?

1.修改UserController代碼,增加注入U(xiǎn)serService的代碼

?

1 package ioc.core.test.controller; 2 3 import ioc.core.annotation.Autowired; 4 import ioc.core.annotation.stereotype.Controller; 5 import ioc.core.test.service.UserService; 6 7 @Controller 8 public class UserController { 9 10 /** 11 * 通過@Autowired可以注入U(xiǎn)serService的對(duì)象。 12 */ 13 @Autowired 14 private UserService userServiceImpl; 15 16 public void login(){ 17 System.out.println("-登錄Controller-"); 18 userServiceImpl.login(); 19 } 20 21 }

?

2.調(diào)用UserController 對(duì)象

1 package ioc.core.test; 2 3 import org.junit.Test; 4 5 import ioc.core.impl.AnntationApplicationContext; 6 import ioc.core.test.config.Config; 7 import ioc.core.test.controller.UserController; 8 9 public class AnntationApplicationContextTest { 10 11 @Test 12 public void login(){ 13 try { 14 AnntationApplicationContext context=new AnntationApplicationContext(Config.class); 15 UserController userController = context.getBean("userController", UserController.class); 16 userController.login(); 17 System.out.println(context.getContext().getObjects()); 18 19 } catch (Exception e) { 20 e.printStackTrace(); 21 } 22 } 23 24 }

3.輸出結(jié)果

同時(shí)輸出了UserController的內(nèi)容和UserService的內(nèi)容

?

轉(zhuǎn)載于:https://www.cnblogs.com/zhuyuejiu/p/7819694.html

創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎(jiǎng)勵(lì)來咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎(jiǎng)

總結(jié)

以上是生活随笔為你收集整理的一起写框架-Ioc内核容器的实现-对象的调用-属性注入容器的对象(十)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。