首页 > 手写简易Spring框架
头像
社交牛逼一号
发布于 2021-09-23 20:43
+ 关注

手写简易Spring框架

我们前面分析很多的Spring源码,现在我们来手写一个简易的Spring源码
创建一个maven工程。

public class Test {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
        UserService userService = context.getBean("UserService", UserService.class);
        userService.test();
    }
}
在我们的通常Spring项目中,一定有这几步,我们想要手写就得先模拟出这几个方法和类。

Autowrite注解的依赖注入实现: 遍历出类中的所有属性,循环他们进行判断是否加了Autowrite注解,通过getBean得到对象,再把得到的对象赋值给instance。(记得开启Accessible)

package com.spring;

import java.io.File;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class LuoChaoApplicationContext {


    //对应AppConfig.class
    private Class configClass;

    //单例池 存放单例bean  确保我们得到得对象都是单例的。
    private ConcurrentHashMap<String,Object> singletonObjects = new ConcurrentHashMap<>();

    //存放BeanDefintion对象的HashMap
    private ConcurrentHashMap<String,BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>();

    //存放BeanPostProcessor集合
    private List<BeanPostProcessor> beanPostProcessorList = new ArrayList<>();

    public LuoChaoApplicationContext(Class configClass) {
        this.configClass = configClass;

        //解析配置类
        // Compontent注解---》扫描路径---》扫描---》BeanDefinition---》beanDefinitionMap
        sacn(configClass);

        //在我们启动的时候就要把所有的单例bean创建好
        /*
        entrySet()的返回值也是返回一个Set集合,此集合的类型为Map.Entry。
         Map.Entry是Map声明的一个内部接口,此接口为泛型,定义为Entry<K,V>。
         它表示Map中的一个实体(一个key-value对)。接口中有getKey(),getValue方法。
         */
        for (Map.Entry<String,BeanDefinition> entry : beanDefinitionMap.entrySet()) {
            //得到bean的名字
            String beanName = entry.getKey();
            BeanDefinition beanDefinition = entry.getValue();
            //判断是否是单例bean
            if (beanDefinition.getScope().equals("singleton")){
                Object bean = createBean(beanName,beanDefinition);
                //是单例的把它放到单例池里面去
                singletonObjects.put(beanName,bean);
            }
        }


    }

    //对应getBean方法
    public Object getBean(String beanName){
        //判断传进来的这个名字有没有对应的bean描述
        if (beanDefinitionMap.containsKey(beanName)){
            BeanDefinition beanDefinition = beanDefinitionMap.get(beanName);
            //判断名字对象的对象是否是单例的
            if (beanDefinition.getScope().equals("singleton")){
                //从单例池中拿到这个对象
                Object o = singletonObjects.get(beanName);
                return o;
            }else {
                //原型bean  创建bean对象。
                Object bean = createBean(beanName,beanDefinition);
                return bean;
            }

        }else {
            //不存在
            throw new NullPointerException();
        }

    }


    // 通过beanDefinition描述创建一个对象
    public Object createBean(String beanName ,BeanDefinition beanDefinition){
        //得到bean的class对象
        Class clazz = beanDefinition.getClazz();
        //通过反射调用无参构造进行bean的创建
        try {
            Object instance = clazz.getDeclaredConstructor().newInstance();

            //依赖注入 (不考虑循环依赖问题)
            // 得到类中的属性
            Field[] declaredFields = clazz.getDeclaredFields();

            for (Field declaredField : clazz.getDeclaredFields()) {
                //判断是否加了自动注入注解。
                if (declaredField.isAnnotationPresent(Autowired.class)){
                    //此处我们先只判断byName 我们调用getBean得到对象
                    Object bean = getBean(declaredField.getName());
                    //判断required是否为false
                    Autowired annotation = declaredField.getAnnotation(Autowired.class);
                    boolean required = annotation.required();
                    //判断bean为空并且required值为false 无法注入值
                    if (bean==null && required){
                        //抛出异常
                        throw new RuntimeException();
                    }
                    //实际上setAccessible是启用和禁用访问安全检查的开关
                    declaredField.setAccessible(true);
                    // 将bean对象赋值给instance属性。
                    declaredField.set(instance,bean);
                }
            }

            //判断是否实现了BeanNameAware接口  也叫做回调
                if (instance instanceof BeanNameAware){
                    ((BeanNameAware) instance).setBeanName(beanName);
                }

                //遍历出所有存放的beanPostProcessor
                for (BeanPostProcessor beanPostProcessor : beanPostProcessorList) {
                    //将对象和名字传入 进行初始化前的操作
                    instance = beanPostProcessor.postProcessBeforeInitialization(instance,beanName);
                }

                //判断是否实现了InitializingBean接口   初始化
                if (instance instanceof InitializingBean){
                    try {
                        ((InitializingBean) instance).afterPropertiesSet();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }

                //遍历出所有存放的beanPostProcessor
                for (BeanPostProcessor beanPostProcessor : beanPostProcessorList) {
                    //将对象和名字传入 进行初始化后的操作
                    instance = beanPostProcessor.postProcessAfterInitialization(instance,beanName);
                }

                //BeanPostProcessor

            //直接返回创建的bean对象
            return instance;
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }


        return null;
    }



    private void sacn(Class configClass) {
        //拿到配置类进行解析
        //解析ComponentScan注解拿到扫描路径进行扫描
        ComponentScan componentScanAnnotation = (ComponentScan) configClass.getDeclaredAnnotation(ComponentScan.class);
        //拿到注解扫描得路径
        String path = componentScanAnnotation.value();

        //进行扫描类上面是否加载了ComponentScan注解
        /**
         * Bootstrap---》jre/lib
         * ext----》jre/ext/lib
         * App----》classpath
          */
        ClassLoader classLoader = LuoChaoApplicationContext.class.getClassLoader();//得到得就是app
        URL resource = classLoader.getResource("com/luochao/service");
        //得到service目录
        File file = new File(resource.getFile());
        //判断是不是一个目录
        if (file.isDirectory()){
            File[] files = file.listFiles();
            for (File file1 : files) {
                //E:\code\springBychaoluo\target\classes\com\luochao\service\UserService.class
                System.out.println(file1.getAbsolutePath());

                /*
                利用类加载加载class对象
                我们要需要得不是所有得路径,我们只需要com.luochao.service.UserService路径
                所以我们进行分解路径
                 */
                String fileName = file1.getAbsolutePath();
                //判断是.class文件才进行截取替换
                if (fileName.endsWith(".class")){
                    String className = fileName.substring(fileName.indexOf("com"), fileName.indexOf(".class"));
                    //com.luochao.service.UserService
                    className  = className.replace("\\", ".");
                    System.out.println(className);

                    try {
                        Class<?> aClass = classLoader.loadClass(className);
                        //判断类上是否有Component注解
                        if (aClass.isAnnotationPresent(Component.class)){
                            //表示当前这个类是一个bean
                            //解析类,判断当前bean是单例bean,还是原型bean 还是prototype的bean
                            // BeanDefinition bean的定义

                            //扫描到了LuoChaoBeanPostProcessor进行是否有实现BeanPostProcessor
                            //判断当前的aclass是否实现了BeanPostProcessor接口
                            if (BeanPostProcessor.class.isAssignableFrom(aClass)){
                                //利用反射得到对象  在spring是使用getBean的方法执行的 使得在BeanPostProcessor中我们也可以自动注入bean对象  但是这里我们就用简单的办法容易理解。
//                                String name = aClass.getName();
//                                BeanPostProcessor instance = (BeanPostProcessor) getBean(name);
//                                beanDefinitionMap.put(name,beanDefinition);
                                BeanPostProcessor instance = (BeanPostProcessor) aClass.getDeclaredConstructor().newInstance();
                                //存放到集合中
                                beanPostProcessorList.add(instance);
                            }

                            Component componentAnnotation = aClass.getDeclaredAnnotation(Component.class);
                            //当前bean类所对应的名字
                            String beanName = componentAnnotation.value();

                            //表示bean的一个定义
                            BeanDefinition beanDefinition = new BeanDefinition();
                            //给beandefinition类的class属性设置值为当前类属性
                            beanDefinition.setClazz(aClass);

                            //判断是否存在scope注解
                            if (aClass.isAnnotationPresent(Scope.class)){
                                //原型bean
                                Scope scopeAnnotation = aClass.getDeclaredAnnotation(Scope.class);
                                beanDefinition.setScope(scopeAnnotation.value());
                            }else {
                                //单例bean 设置它对应的描述为单例的
                                beanDefinition.setScope("singleton");
                            }
                            //存放拿到的beanName
                            beanDefinitionMap.put(beanName,beanDefinition);
                        }
                    } catch (ClassNotFoundException e) {
                        e.printStackTrace();
                    } catch (InstantiationException e) {
                        e.printStackTrace();
                    } catch (InvocationTargetException e) {
                        e.printStackTrace();
                    } catch (NoSuchMethodException e) {
                        e.printStackTrace();
                    } catch (IllegalAccessException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }



}

//Bean的描述类
public class BeanDefinition {

    //bean的类型
    private Class clazz;
    //是否是原型bean
    private String scope;


    public Class getClazz() {
        return clazz;
    }

    public void setClazz(Class clazz) {
        this.clazz = clazz;
    }

    public String getScope() {
        return scope;
    }

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

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;


//自动注入
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD,ElementType.FIELD})
public @interface Autowired {
    String value() default "";

    boolean required() default true;
}

package com.spring;

//回调
public interface BeanNameAware {

    void setBeanName(String name);
}

package com.spring;

//AOP的最终归宿
public interface BeanPostProcessor {

    //初始化前
    Object postProcessBeforeInitialization(Object bean, String beanName);

    //初始化后
    Object postProcessAfterInitialization(Object bean, String beanName);


}

package com.spring;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

//生成bean注解
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Component {
    String value() default "";
}

package com.spring;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

//扫描注解
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface ComponentScan {

    String value();
}

package com.spring;

//初始化
public interface InitializingBean {

    void afterPropertiesSet() throws Exception;
}

package com.spring;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

//原型bean标签
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Scope {
    String value();

    //单例bean是指我们在测试类中通过getbean多次得到得对象是同一个  原型bean得到得则是不同得对象
}

package com.luochao.service;


import com.spring.BeanPostProcessor;
import com.spring.Component;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;


//将具体的AOP代理逻辑封装成一个LuoChaoBeanPostProcessor放入Spring容器中
@Component
public class LuoChaoBeanPostProcessor implements BeanPostProcessor {

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) {
        if (beanName.equals("userService")){
            System.out.println("初始化前");
            ((UserService)bean).setBeanName("我是帅哥");
        }
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) {
        System.out.println("初始化后");
        //模拟简易的AOP 这里就可以判断是否要aop
        if (beanName.equals("userService")){
            /*
            JDK动态代理生成一个代理对象
            在spring源码中 开启Aop就是在Spring容器中生成一个BeanPostProcessor的Bean对象
             放到Spring容器中去
             */
            Object proxyInstance = Proxy.newProxyInstance(LuoChaoBeanPostProcessor.class.getClassLoader(), bean.getClass().getInterfaces(), new InvocationHandler() {
                @Override
                public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                    //找到jionpoint 切点
                    System.out.println("AOP代理逻辑");
                    // 执行bean中的方法进行代理
                    return method.invoke(bean,args);
                }
            });
            //代理对象
            return proxyInstance;
        }
        return bean;
    }
}

package com.luochao.service;

import com.spring.Component;

@Component("peopleService")
public class PeopleService {


}

package com.luochao.service;

public interface UserService {

    void test();

    void setBeanName(String beanName);
}

package com.luochao.service;

import com.spring.Autowired;
import com.spring.Component;
import com.spring.InitializingBean;


@Component("userService")
public class UserServiceImpl implements UserService {

    @Autowired
    private PeopleService peopleService;

    private String beanName;

    public void setBeanName(String beanName) {
        this.beanName = beanName;
    }

    // Aware 回调
    //    @Override
    //    public void setBeanName(String name) {
    //        beanName = name;
    //    }

    public void test(){
        System.out.println(peopleService);
        System.out.println(beanName);
    }


//    //初始化
//    @Override
//    public void afterPropertiesSet() throws Exception {
//        System.out.println("初始化");
//    }
}

package com.luochao;

import com.spring.ComponentScan;

// 扫描启动类
@ComponentScan("com.luochao.service")
public class AppConfig {
}

package com.luochao;

import com.luochao.service.UserService;
import com.luochao.service.UserServiceImpl;
import com.spring.LuoChaoApplicationContext;

public class Test {

    public static void main(String[] args) {
        LuoChaoApplicationContext luoChaoApplicationContext = new LuoChaoApplicationContext(AppConfig.class);
        UserService userService = (UserService) luoChaoApplicationContext.getBean("userService");
        userService.test();
        //1.代理对象   2.业务test

    }
}
————————————————
版权声明:本文为CSDN博主「本来写bug却写成了程序」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/m0_57560984/article/details/120442976

全部评论

(0) 回帖
加载中...
话题 回帖

近期热帖

热门推荐