当先锋百科网

首页 1 2 3 4 5 6 7

我们前面分析很多的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)

创建一个扫描注解 创建bean注解  一个scope判断是否是单例注解  在启动类上配置扫描注解,给扫描路径   创一个Annotationcontext类  有get bean方法。通过得到注解扫描的类,通过App扫描得到注解所需要扫描的地址,通过截取 替换路径,解析成为com.user.service字符串,把他放入到classloader.loadclass中得到class对象 判断对象上是否有component注解,得到当前bean对应的名字    (创建beandefinition描述类  里面有 scope  class属性 )设置bd的class属性为当前类属性    判断当前类是否有原型bean注解  没有就设置它的描述scope为单例  有就设置它为注解上的值     最后将它们放入beandefinitionmap中        当我们在getbean的时候  传入beanName 我们在bdMap中去找   找到了则进行判断是否为单例bean  是则直接返回这里返回的bean对象都是一样的,称之为单例bean     不是则通过bd中的class类通过反射进行创建,这里每创建的bean都是不一样的   不存在就抛出异常     当然spring在启动的时候就把bean对象创建好了  我们通过循环bad.enteyset  得到bean名字和bd  判断是否是单例的,是就直接放入单例池。

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();
                    }
                }
            }
        }
    }
​
​
​
}
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;
    }
}
//Bean的描述类
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
​
    }
}
至此我们模拟了Spring的扫描bean 并且注入bean 简易的Aop 简易的回调  还有单例池。后面继续完善。

迈出这一小步,一定能跨上山巅。