1. 程式人生 > >基於註解方式純手寫spring-ioc

基於註解方式純手寫spring-ioc

1.定義註解


@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface ExtService {

}

2.工具類

https://blog.csdn.net/qq_41988225/article/details/84393804

3.主要功能類

package com.wangyu.extspring.annotation;

import java.lang.reflect.Field;
import java.util.List;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;

import org.apache.commons.lang.StringUtils;

/**
 * 手寫ioc註解版本 
 *
 */

public class ExtClassPathXmlApplicationContext {

    //掃包範圍
    private String                                   packageName;
    //儲存加了註解的類
    private static ConcurrentHashMap<String, Object> beansMap = null;

    public ExtClassPathXmlApplicationContext(String packageName) throws Exception {
        beansMap = new ConcurrentHashMap<String, Object>();
        if (StringUtils.isEmpty(packageName)) {
            return;
        }
        this.packageName = packageName;
        initBeans();
        initEntryField();
    }

    //給容器中的物件的初始化屬性
    public void initEntryField() throws Exception {
        //遍歷所有的bean容器物件,判斷是否加了extresource註解
        for (Entry<String, Object> entry : beansMap.entrySet()) {
            String key = entry.getKey();
            Object object = entry.getValue();
            attrAssion(object);
        }

    }

    //獲取bean
    public Object getBean(String beanId) throws Exception {
        if (StringUtils.isEmpty(beanId)) {
            throw new Exception("該beanid是空的");
        }
        //從spring容器獲取bean
        Object object = beansMap.get(beanId);
        /**if (object == null) {
            throw new Exception("class not found ");
        }*/
        //3.使用反射機制進行初始化
        return object;
    }

    //初始化物件
    public void initBeans() throws Exception {
        //1.使用java反射機制,獲取當前包下的所有類
        List<Class<?>> classes = ClassUtil.getClasses(packageName);
        //2.判斷類上面是否有註解
        ConcurrentHashMap<String, Object> classExisAnnotation = findClassExisAnnotation(classes);
        if (classExisAnnotation == null) {
            throw new Exception("該包的類沒有加註解");
        }

    }

    public ConcurrentHashMap<String, Object> findClassExisAnnotation(List<Class<?>> classes) throws ClassNotFoundException, InstantiationException,
                                                                                            IllegalAccessException {
        for (Class<?> classInfo : classes) {
            ExtService annotation = classInfo.getAnnotation(ExtService.class);
            if (annotation != null) {
                //類名小寫作為beanId
                String className = classInfo.getSimpleName();
                String beanId = toLowerCaseFirstOne(className);
                Object newInatance = newInatance(classInfo);
                beansMap.put(beanId, newInatance);
                continue;
            }
        }
        return beansMap;
    }

    // 首字母轉小寫
    public static String toLowerCaseFirstOne(String s) {
        if (Character.isLowerCase(s.charAt(0)))
            return s;
        else
            return (new StringBuilder()).append(Character.toLowerCase(s.charAt(0))).append(s.substring(1)).toString();
    }

    //建立物件
    public Object newInatance(Class<?> classInfo) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
        return classInfo.newInstance();
    }

    //依賴注入原理分析
    public void attrAssion(Object object) throws Exception {
        Class<? extends Object> classInfo = object.getClass();
        //獲取屬性
        Field[] declaredFields = ((Class<?>) classInfo).getDeclaredFields();
        for (Field field : declaredFields) {
            ExtResource annotation = field.getAnnotation(ExtResource.class);
            if (annotation != null) {
                //獲取屬性名稱
                String beanId = field.getName();
                Object bean = getBean(beanId);
                if (bean != null) {
                    //預設使用屬性名稱,查詢容器物件(當前物件,給屬性賦值 )
                    field.setAccessible(true);
                    //給容器中的物件的屬性進行賦值
                    field.set(object, bean);
                }
            }
        }

    }
}

4.測試

public class ExtTest {
    public static void main(String[] args) throws Exception {
        ExtClassPathXmlApplicationContext ext = 
                new ExtClassPathXmlApplicationContext("com.wangyu.extspring.annotation.service");
        UserService bean = (UserService) ext.getBean("userService5");
        System.out.println(bean);
    }
}