一塊兒寫框架-Ioc內核容器的實現-對象的調用-方法注入容器的對象(十一)

實現功能

就是在方法的上面加入@Autowired註解,容器中的對象會注入到對應類型的參數。ide

注意:暫時實現注入一個對象。全部方法的參數列表的參數只能有一個。測試

實現思路

其實實現的思路和給字段注入的邏輯是同樣的。遍歷類全部的方法有沒有@Autowired,有的就給它賦予容器中對應的對象。this

 

實現步驟

1. 在AbstractApplicationContext增長兩個方法區分屬性注入(autowiredField)和方法注入(autowiredMethodspa

 

 1 /**
 2      * 屬性注入
 3      * @param object
 4      * @param context
 5      * @throws IllegalArgumentException
 6      * @throws IllegalAccessException
 7      */
 8     private void autowiredField(Object object,Context context) throws IllegalArgumentException, IllegalAccessException {
 9         // 5.得到對象的表結構
10         Class<? extends Object> classType = object.getClass();
11         // 6.得到字段的結構
12         Field[] fields = classType.getDeclaredFields();
13         for (int i = 0; i < fields.length; i++) {
14             // autowired得到註解
15             Autowired autowired = fields[i].getAnnotation(Autowired.class);
16             if (autowired != null) {
17                 Class<?> fieldType = fields[i].getType();
18                 String fieldName = fields[i].getName();
19                 // 若是容器裏面有對應的對象
20                 Object fieldObject = context.getObject(fieldType, fieldName);
21                 // 容許訪問私有方法
22                 if (fieldObject != null) {
23                     // 屬性是私有的也能夠訪問
24                     fields[i].setAccessible(true);
25                     // 將屬性值賦予這個對象的屬性
26                     fields[i].set(object, fieldObject);
27                 }
28 
29             }
30         }
31     }
32     /**
33      * 注意set方法的規範
34      * 限定方法只能注入一個參數,而且注入對象的方法只能有一個參數
35      * @param object
36      * @param context
37      * @throws IllegalArgumentException
38      * @throws IllegalAccessException
39      * @throws InvocationTargetException
40      */
41     private void autowiredMethod(Object object,Context context) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException {
42         // 5.得到對象的表結構
43         Class<? extends Object> classType = object.getClass();
44         // 6.得到類方法的結構
45         Method[] methods = classType.getDeclaredMethods();
46         for (int i = 0; i < methods.length; i++) {
47             // autowired得到註解
48             Autowired autowired = methods[i].getAnnotation(Autowired.class);
49             if (autowired != null) {
50                 //得到參數列表的類型
51                 Class<?>[] parameterTypes = methods[i].getParameterTypes();
52                 
53                 String fieldName = methods[i].getName();
54                 
55                 // 若是容器裏面有對應的對象,限定一個方法只能注入一個對象
56                 Object methodObject = context.getObject(parameterTypes[0], fieldName);
57                 // 容許訪問私有方法
58                 if (methodObject != null) {
59                     // 屬性是私有的也能夠訪問
60                     methods[i].setAccessible(true);
61                     // 將屬性值賦予這個對象的屬性
62                     methods[i].invoke(object, methodObject);
63                 }
64 
65             }
66         }
67     }

 

2.修改autowired方法的邏輯。將原來只遍歷屬性的@Autowired註解,修改成同時遍歷屬性和方法上面的的對象注入註解@Autowiredcode

    /**
     * 給對象的屬性注入關聯的對象
     * @throws IllegalArgumentException
     * @throws IllegalAccessException
     * @throws InvocationTargetException 
     */
    private void autowired() throws IllegalArgumentException, IllegalAccessException, InvocationTargetException {
        // 1.得到容器
        Context context = contexts.get();
        // 2.得到容器中的全部對象。
        Map<String, Object> objects = context.getObjects();
        // 3.得到容器中全部的對象值
        Collection<Object> values = objects.values();
        // 4.得到對象的迭代器
        Iterator<Object> iterator = values.iterator();
        while (iterator.hasNext()) {
           Object object = iterator.next();
           //1.注入到屬性
            this.autowiredField(object, context);
            //2.注入到方法
            this.autowiredMethod(object, context);
        }
    }

測試代碼

測試目錄結構對象

1.在UserServiceImpl類裏面增長經過方法注入UserDAO的註解blog

 1 package ioc.core.test.service.impl;
 2 
 3 import ioc.core.annotation.Autowired;
 4 import ioc.core.annotation.stereotype.Service;
 5 import ioc.core.test.dao.UserDAO;
 6 import ioc.core.test.service.UserService;
 7 
 8 /**
 9  * 一個普通的類,用於測試是否能夠建立對象
10  * @author ranger
11  *
12  */
13 @Service
14 public class UserServiceImpl implements UserService {
15     
16     @Autowired
17     private UserDAO userDAO;
18     
19     @Override
20     public void login(){
21         System.out.println("-登陸Service-");
22         userDAO.save();
23     }
24 
25 }

2.測試類調用UserController的對象get

 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.測試結果,同時能夠調用UserController,UserServiceImpl,UserDAO對象。說明成功!it

相關文章
相關標籤/搜索