手寫模擬Spring底層原理實現掃描、創建單例/原型bean,依賴注入,aware回調,aop,後置處理器,初始化等操作

代碼結構

模擬spring源碼

BeanDefinition

public class BeanDefinition {

    private Class aClass;
    private String scope;
    private Boolean lazy;

    public Class getaClass() {
        return aClass;
    }

    public void setaClass(Class aClass) {
        this.aClass = aClass;
    }

    public String getScope() {
        return scope;
    }

    public void setScope(String scope) {
        this.scope = scope;
    }

    public Boolean getLazy() {
        return lazy;
    }

    public void setLazy(Boolean lazy) {
        this.lazy = lazy;
    }
}

BeanNameAware

public interface BeanNameAware {

    void setBeanName(String beanName);
}

BeanPostProcessor

public interface BeanPostProcessor {

    default Object postProcessBeforeInitialization(Object bean, String beanName) {
        return bean;
    }

    /**
     * 初始化後,創建bean的過程中,每一個bean都會調用此方法,也可以單獨判斷,可以用來實現aop
     */
    default Object postProcessAfterInitialization(Object bean, String beanName) {
        return bean;
    }
}

InitializingBean

public interface InitializingBean {
    void afterPropertiesSet();
}

MyApplicationContext

public class MyApplicationContext {

    private Map<String, BeanDefinition> beanDefinitionMap = new HashMap<>();
    //單例池
    private Map<String, Object> singletonObjects = new HashMap<>();

    private List<BeanPostProcessor> beanPostProcessorList = new ArrayList<>();

    public MyApplicationContext(Class<MyAppConfig> myAppConfigClass) throws ClassNotFoundException, NoSuchMethodException {

        //掃描 構建Bean定義,放在beanDefinitionMap中
        scan(myAppConfigClass);
        //掃描完,遍歷beanDefinitionMap,找出所有的單例bean,創建單例bean並放在單例池中
        //單例模式先創建bean再放在單例池中
        Set<Map.Entry<String, BeanDefinition>> entries = beanDefinitionMap.entrySet();
        for (Map.Entry<String, BeanDefinition> entry : entries) {
            String beanName = entry.getKey();
            BeanDefinition beanDefinition = entry.getValue();
            String scope = beanDefinition.getScope();
            if ("singleton".equals(scope)) {
                Object singletonBean = createBean(beanName, beanDefinition);
                singletonObjects.put(beanName, singletonBean);
            }
        }


    }

    private void scan(Class<?> myAppConfigClass) throws ClassNotFoundException {
        if (myAppConfigClass.isAnnotationPresent(MyComponentScan.class)) {
            MyComponentScan annotation = myAppConfigClass.getAnnotation(MyComponentScan.class);
            //掃描路徑
            String path = annotation.value();
            System.out.println("掃描路徑:" + path);
            path = path.replace(".", "/");

            ClassLoader classLoader = MyApplicationContext.class.getClassLoader();
            URL resource = classLoader.getResource(path);
            File fileDirectory = new File(resource.getFile());
            if (fileDirectory.isDirectory()) {
                File[] files = fileDirectory.listFiles();
                //遍歷class文件
                for (File file : files) {
                    String absolutePath = file.getAbsolutePath();
                    //System.out.println("absolutePath->" + absolutePath);
                    //加載類
                    //轉換路徑格式
                    absolutePath = absolutePath.substring(absolutePath.indexOf("com"), absolutePath.lastIndexOf(".class"));
                    absolutePath = absolutePath.replace("\\", ".");
                    //System.out.println("absolutePath->" + absolutePath);
                    //class文件加載爲class對象
                    //Class<?> aClass = Class.forName(absolutePath);
                    Class<?> aClass = classLoader.loadClass(absolutePath);
                    //找到有Component註解的類
                    if (aClass.isAnnotationPresent(MyComponent.class)) {
                        System.out.println(absolutePath + "有component註解");

                        //如果一個類有component註解,再判斷是否實現了BeanPostProcessor接口
                        if (BeanPostProcessor.class.isAssignableFrom(aClass)) {
                            try {
                                BeanPostProcessor instance = (BeanPostProcessor) aClass.getConstructor().newInstance();
                                //保存BeanPostProcessor,等到創建bean的時候再使用
                                beanPostProcessorList.add(instance);

                            } catch (InstantiationException e) {
                                e.printStackTrace();
                            } catch (IllegalAccessException e) {
                                e.printStackTrace();
                            } catch (InvocationTargetException e) {
                                e.printStackTrace();
                            } catch (NoSuchMethodException e) {
                                e.printStackTrace();
                            }
                            //不用獲取BeanPostProcessor的BeanDefinition
                        } else {
                            MyComponent myComponent = aClass.getAnnotation(MyComponent.class);
                            //註解中配置的beanName
                            String beanName = myComponent.value();
                            //如果未指定beanName
                            if ("".equals(beanName)) {
                                //根據類型生成名字
                                beanName = Introspector.decapitalize(aClass.getSimpleName());
                            }
                            //如果有類有Component這個註解,那麼需要創建一個BeanDefinition描述該bean
                            BeanDefinition beanDefinition = new BeanDefinition();
                            beanDefinition.setaClass(aClass);
                            //再判斷是單例還是原型
                            if (aClass.isAnnotationPresent(MyScope.class)) {
                                MyScope myScope = aClass.getAnnotation(MyScope.class);
                                String scope = myScope.value();
                                beanDefinition.setScope(scope);
                            } else {
                                //沒有註解,默認是單例,如果是單例
                                beanDefinition.setScope("singleton");
                            }
                            beanDefinitionMap.put(beanName, beanDefinition);
                        }

                    }
                }
            }
        }
    }


    public Object getBean(String beanName) throws NoSuchMethodException {
        //如果沒有則說明沒有定義這個bean
        if (!beanDefinitionMap.containsKey(beanName)) {
            System.out.println("找不到該bean");
            return null;
        }
        BeanDefinition beanDefinition = beanDefinitionMap.get(beanName);
        String scope = beanDefinition.getScope();
        //如果是單例,直接從單例池中獲取
        if ("singleton".equals(scope)) {
            Object singletonBean = singletonObjects.get(beanName);
            //可能因爲掃描順序問題,還沒有初始化成功
            if (singletonBean == null) {
                singletonBean = createBean(beanName, beanDefinition);
                singletonObjects.put(beanName, singletonBean);
            }
            return singletonBean;
        } else {
            //原型模式每次都要重新創建
            Object prototypeBean = createBean(beanName, beanDefinition);
            return prototypeBean;
        }
    }

    //創建bean
    public Object createBean(String beanName, BeanDefinition beanDefinition) throws NoSuchMethodException {
        Class aClass = beanDefinition.getaClass();
        //調用構造方法創建對象
        Object instance = null;
        try {
            instance = aClass.getConstructor().newInstance();
            //創建bean的過程中進行依賴注入
            //遍歷類的屬性
            Field[] fields = aClass.getDeclaredFields();
            for (Field field : fields) {
                //判斷屬性上是否有autowired註解
                if (field.isAnnotationPresent(MyAutowired.class)) {
                    field.setAccessible(true);
                    //賦值 -> 先根據類型再根據名字去找,我們這裏只使用名字去找 會有循環依賴問題
                    field.set(instance, getBean(field.getName()));
                }
            }

            //依賴注入完成後,beanNameAware
            if (instance instanceof BeanNameAware) {
                ((BeanNameAware) instance).setBeanName(beanName);
            }

            //初始化前
            for (BeanPostProcessor beanPostProcessor : beanPostProcessorList) {
                instance = beanPostProcessor.postProcessBeforeInitialization(instance, beanName);
            }

            //依賴注入完成之後進行初始化操作
            //判斷是否實現了InitializingBean接口
            if (instance instanceof InitializingBean) {
                ((InitializingBean) instance).afterPropertiesSet();
            }

            //初始化後
            //new MyBeanPostProcessor().postProcessAfterInitialization(instance, beanName);
            for (BeanPostProcessor beanPostProcessor : beanPostProcessorList) {
               instance = beanPostProcessor.postProcessAfterInitialization(instance, beanName);
            }

        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
        return instance;
    }

}

MyAutowired

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface MyAutowired {

    String value() default "";
}

MyComponent

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface MyComponent {
    String value() default "";
}

MyComponentScan

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

    String value() default "";
}

MyScope

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

    String value() default "";
}

測試代碼

MyAppConfig

@MyComponentScan("com.sy.test")
public class MyAppConfig {
}

MyBeanPostProcessor

@MyComponent
public class MyBeanPostProcessor implements BeanPostProcessor {

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) {
        //創建bean的過程中,每一個bean都會調用此方法,也可以單獨判斷
        if ("orderService".equals(beanName)) {
            System.out.println("生成orderService的代理對象");
            Object proxyInstance = Proxy.newProxyInstance(MyBeanPostProcessor.class.getClassLoader(), bean.getClass().getInterfaces(), new InvocationHandler() {
                @Override
                public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                    //切面邏輯
                    System.out.println(beanName + "執行切面邏輯");
                    return method.invoke(bean, args);
                }
            });
            return proxyInstance;
        } else {
            System.out.println(beanName + "執行bean的後置處理器");
            return bean;
        }
    }
}

MyValue

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface MyValue {
    String value() default "";
}

MyValueBeanPostProcessor

@MyComponent
public class MyValueBeanPostProcessor implements BeanPostProcessor {

    /**
     * 測試通過自定義註解給屬性賦值
     */
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) {
        Field[] declaredFields = bean.getClass().getDeclaredFields();
        for (Field field : declaredFields) {
            if (field.isAnnotationPresent(MyValue.class)) {
                field.setAccessible(true);
                MyValue annotation = field.getAnnotation(MyValue.class);
                String value = annotation.value();
                try {
                    field.set(bean,value);
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            }
        }
        return bean;
    }

}

OrderInterface

public interface OrderInterface {
    void test();
}

OrderService

@MyComponent
@MyScope("prototype")
public class OrderService implements OrderInterface, InitializingBean {

    @MyAutowired
    private UserService userService;

    @MyValue("xxxxxx")
    private String testStr;

    @Override
    public void test() {
        System.out.println("myOrderService.test..........");
        System.out.println("myOrderService.myUserService->" + userService);
        System.out.println("myOrderService.testStr->" + testStr);
    }

    @Override
    public void afterPropertiesSet() {
        System.out.println("myOrderService.afterPropertiesSet...");
    }
}

UserService

@MyScope("singleton")
@MyComponent("userService")
public class UserService implements InitializingBean, BeanNameAware {

    private String beanName;

    public void test() {
        System.out.println("myUserService.test..............");
    }

    @Override
    public void afterPropertiesSet() {
        System.out.println("myUserService.afterPropertiesSet...");
    }

    @Override
    public void setBeanName(String beanName) {
        System.out.println("userService.setBeanName...");
        this.beanName = beanName;
    }
}

TestSpring

public class TestSpring {


    @Test
    public void testCreateBean() throws ClassNotFoundException, NoSuchMethodException {

        //首先掃描 -> 創建單例bean BeanDefinition BeanPostProcessor
        MyApplicationContext applicationContent = new MyApplicationContext(MyAppConfig.class);

        UserService userService = (UserService) applicationContent.getBean("userService");
        userService.test();

        System.out.println("userService->" + applicationContent.getBean("userService"));
        System.out.println("userService->" + applicationContent.getBean("userService"));

        OrderInterface orderService = (OrderInterface) applicationContent.getBean("orderService");
        orderService.test();

        System.out.println("orderService->" + applicationContent.getBean("orderService"));
        System.out.println("orderService->" + applicationContent.getBean("orderService"));
        
    }

}

測試結果

源碼下載

spring_sy.rar

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章