Java-第十五部分-源码解读-手写Spring

402 阅读4分钟

源码解读全文

手写Spring

自定义使用类和接口

UserService

  • BeanNameAware实现回调设置BeanName的功能setBeanName
  • InitializingBeanBean创建时,进行一些初始化afterPropertiesSet
@Component("userService")
public class UserService implements BeanNameAware, InitializingBean, UserInterface {
    @Autowired
    private OrderService orderService;

    private String beanName; //通过Spring设置beanName
    private String name;
    public void test() {
        System.out.println(orderService);
    }

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

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

UserInterface

  • 实现AOP代理类逻辑
public interface UserInterface {
    public void test();
}

OrderService

  • 被依赖注入类
@Component
public class OrderService {
}

自定义注解

ComponentScan

  • 扫描类
@Retention(RetentionPolicy.RUNTIME) //祝保留到class字节码文件中
@Target(ElementType.TYPE) //作用在类上
public @interface ComponentScan {
    String value() default ""; //指定扫描路径
}

Component

  • 标识Bean类自动注册
@Retention(RetentionPolicy.RUNTIME) //祝保留到class字节码文件中
@Target(ElementType.TYPE) //作用在类上
public @interface Component {
    String value() default ""; //给当前的注入类取一个名字
}

Autowired

  • 依赖注入
@Retention(RetentionPolicy.RUNTIME) //祝保留到class字节码文件中
@Target(ElementType.FIELD) //作用在类上
public @interface Autowired {

}

Scope

  • 处理单例与多例
@Retention(RetentionPolicy.RUNTIME) //祝保留到class字节码文件中
@Target(ElementType.TYPE) //作用在类上
public @interface Scope {
    String value() default ""; //指定单例 还是 多例
}

自定义接口

BeanNameAware

  • 实现回调,设置beanName
public interface BeanNameAware {
    public void setBeanName(String beanName);
}

InitializingBean

  • Bean初始化接口
public interface InitializingBean {
    public void afterPropertiesSet();
}

BeanPostProcessor

  • Bean处理器,在初始化前后进行自定义处理
public interface BeanPostProcessor {
    //初始化前执行
    public Object postProcessBeforeInitialization(String beanName, Object bean);
    //初始化后执行
    public Object postProcessAfterInitialization(String beanName, Object bean);
}

InitBeanPostProcessor

  • 实现了BeanPostProcessor,维护Bean的初始化过程,需要自动注册到IOC容器中
//自定义的类处理器,维护bean的初始化过程
@Component
public class InitBeanPostProcessor implements BeanPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(String beanName, Object bean) {
        if (beanName.equals("userService")) {
            System.out.println("userService" + " - " + bean + " - postProcessBeforeInitialization");
        }
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(String beanName, Object bean) {
        if (beanName.equals("userService")) {
            Object proxyInstance = Proxy.newProxyInstance(bean.getClass().getClassLoader(),
                    bean.getClass().getInterfaces(),
                    new InvocationHandler() {
                        @Override
                        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                            System.out.println("postProcessAfterInitialization - Proxy");
                            method.invoke(bean, args);
                            return null;
                        }
                    });
            return proxyInstance;
        }
        return bean;
    }
}

配置类

  • 表明扫描的包的位置
@ComponentScan("com.java.service")
public class AppConfig {
}

BeanDefinition

  • 记录Bean的信息
public class BeanDefinition {
    private Class type;
    private String scope;

    public Class getType() {
        return type;
    }

    public void setType(Class type) {
        this.type = type;
    }

    public String getScope() {
        return scope;
    }

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

Context

  • SpringIOC容器,其实就是Context上下文
  • 代码按标题分割了,合起来就好(提醒自己)

维护相关信息的集合

public class InitSpringApplicationContext {
    //传入的配置类
    private Class configClass;
    //保存bean-BeanDefinition
    private ConcurrentHashMap<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>();
    //保存单例bean
    private ConcurrentHashMap<String, Object> singletonObjects = new ConcurrentHashMap<>();
    //保存BeanPostProcessor 后置处理器
    private ArrayList<BeanPostProcessor> beanPostProcessorList = new ArrayList<>();

处理配置类的信息

  • 实际目的是为了获取配置类的上,需要扫描的包下的class文件
    public InitSpringApplicationContext(Class configClass) {
        this.configClass = configClass;
        //扫描
        //获取扫描路径,获取bean beanDefinition
        if (configClass.isAnnotationPresent(ComponentScan.class)) {
            ComponentScan componentScan = (ComponentScan) configClass.getAnnotation(ComponentScan.class);
            String scanPath = componentScan.value(); //实际上是包名
            scanPath = scanPath.replace(".", "/"); //转换成路径 com/java/service
            //需要扫描包下面的class,还需要是`out下`经过编译过的class字节码文件
            ClassLoader classLoader = InitSpringApplicationContext.class.getClassLoader();
            // /Users/mzx/Desktop/java/spring-source/init-spring/out/production/init-spring + /scanPath
            // 项目的输出路径 + 扫描路径
            URL resource = classLoader.getResource(scanPath);//将相对路径转化为绝对路径
            File file = new File(resource.getFile());

            if (file.isDirectory()) { //当前是否是文件夹
                File[] files = file.listFiles();
                //输出项目的绝对路径/Users/mzx/Desktop/java/spring-source/init-spring/out/production/init-spring/
                int len = classLoader.getResource("").getPath().length();

实例化Bean

  • 获取全类名
  • 处理后置处理器并加入beanPostProcessorList
  • 获取beanName,默认为首字母小写,用Introspector处理
  • 生成对应的beanDefinition,保存在beanDefinitionMap
                for (File f : files) {
                    //获取当前扫描路径下文件的绝对路径
                    String fileName = f.getAbsolutePath();
                    if (fileName.endsWith(".class")) {
                        String className = fileName.substring(len, fileName.indexOf(".class"));
                        className = className.replace("/", ".");
                        //判断这个类是否是一个Bean
                        //通过反射,判断当前类是否被`Component`修饰
                        //需要获取类的全限定名 包名+类名
                        try {
                            Class<?> clazz = classLoader.loadClass(className);
                            if (clazz.isAnnotationPresent(Component.class)) {
                                //判断是否为后置处理器
                                if (BeanPostProcessor.class.isAssignableFrom(clazz)) { //从类的角度去判断是否为clazz的父类
                                    BeanPostProcessor instance = (BeanPostProcessor) clazz.newInstance();
                                    beanPostProcessorList.add(instance);
                                    continue; //如果为后置处理器,就不加入map中,直接加入处理器list中
                                }
                                String beanName = clazz.getAnnotation(Component.class).value();
                                if (beanName.equals("")) { //默认生成beanname
                                    //首字母小写
                                    beanName = Introspector.decapitalize(clazz.getSimpleName());
                                }
                                //处理Bean 需要处理多例Bean 和 单例Bean的情况
                                BeanDefinition beanDefinition = new BeanDefinition();
                                if (clazz.isAnnotationPresent(Scope.class)) {
                                    String scope = clazz.getAnnotation(Scope.class).value();
                                    beanDefinition.setScope(scope);
                                } else {
                                    beanDefinition.setScope("singleton");
                                }
                                //设置类型
                                beanDefinition.setType(clazz);
                                //保存beanDefinition
                                beanDefinitionMap.put(beanName, beanDefinition);
                            }
                        } catch (ClassNotFoundException e) {
                            e.printStackTrace();
                        } catch (InstantiationException e) {
                            e.printStackTrace();
                        } catch (IllegalAccessException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        }

处理单例Bean

  • 直接创建出来,且只创建一份
  • (其实可以不用这一步)
        //将单例bean都创建出来
        for (String beanName : beanDefinitionMap.keySet()) {
            BeanDefinition beanDefinition = beanDefinitionMap.get(beanName);
            if (beanDefinition.getScope().equals("singleton")) {
                Object bean = createBean(beanName, beanDefinition);
                //保存单例bean对象
                singletonObjects.put(beanName, bean);
            }
        }
    }

createBean

  • 真正进行Bean的实例化
  • 处理依赖注入
  • 回调赋值beanName
  • 进行初始化前的操作
  • 进行初始化
  • 进行初始化后的操作,返回了一个代理对象
    private Object createBean(String beanName, BeanDefinition beanDefinition) {
        Class clazz = beanDefinition.getType();
        try {
            //实例化
            Object instance = clazz.getConstructor().newInstance();
            //在创建bean的时候,为bean的属性进行赋值
            //依赖注入 Autowired 先Type,在类名
            for (Field f : clazz.getDeclaredFields()) {
                if (f.isAnnotationPresent(Autowired.class)) {
                    f.setAccessible(true); //暴力反射
                    //通过这个属性名,找一个bean对象,进行注入
                    f.set(instance, getBean(f.getName()));
                }
            }
            //回调 赋值beanName
            if (instance instanceof BeanNameAware) {
                //检查这个实例是否实现了这个接口
                //就将这个beanName重新赋值给该类实例
                ((BeanNameAware) instance).setBeanName(beanName);
            }
            //初始化前进行的工作
            for (BeanPostProcessor beanPostProcessor : beanPostProcessorList) {
                instance = beanPostProcessor.postProcessBeforeInitialization(beanName, instance);
            }
            //初始化机制
            if (instance instanceof InitializingBean) {
                //检查这个实例是否实现了这个接口
                //就将这个beanName重新赋值给该类实例
                ((InitializingBean) instance).afterPropertiesSet();
            }
            //初始化后 AOP 切片编程 加强方法,最终返回的应该是代理对象
            for (BeanPostProcessor beanPostProcessor : beanPostProcessorList) {
                instance = beanPostProcessor.postProcessAfterInitialization(beanName, instance);
            }
            return instance;
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }

        return null;
    }

getBean

  • 单例Bean,从集合中获取,没有创建
  • 多例Bean,每次要用都创建
    //获取Bean对象
    public Object getBean(String beanName) {
        BeanDefinition beanDefinition = beanDefinitionMap.get(beanName);
        if (beanDefinition == null) { //没有这个bean
            throw new NullPointerException();
        } else {
            String scope = beanDefinition.getScope();
            //单例bean的处理
            if (scope.equals("singleton")) { //单例
                //生成唯一的单例bean
                Object bean = singletonObjects.get(beanName);
                if (bean == null) {
                    //当创建第一个对象,但是需要注入第二个对象时,第二个对象的bean不存在,那么直接创建一个
                    bean = createBean(beanName, beanDefinition);
                    singletonObjects.put(beanName, bean);
                }
                return bean;
            } else { //多例
                return createBean(beanName, beanDefinition);
            }
        }
    }
}

使用

  • AppConfig配置类加入
public class Test {
    public static void main(String[] args) {
        InitSpringApplicationContext isac = new InitSpringApplicationContext(AppConfig.class);
        UserInterface userService = (UserInterface) isac.getBean("userService");
        userService.test();
    }
}