标签搜索

目 录CONTENT

文章目录

手写框架之SpringIOC和AOP

陈铭
2021-07-11 / 6 评论 / 6 点赞 / 721 阅读 / 2,319 字 / 正在检测是否收录...

ApplicationContext

职责作用

该类是模拟Spring的IOC环境,为bean的生命周期提供存活环境。所以它维护了类池、BeanDefinition池、单例池和切面池。

    private static Class config;
    private static List aopClassList=new CopyOnWriteArrayList();; //切面池
    private static List aopPointCutList= new CopyOnWriteArrayList(); //切点池
    private static List classList=new CopyOnWriteArrayList(); //类池
    private static Map beanDefinitionMap = new ConcurrentHashMap();//BeanDefinition池
    private static Map singletonObjects = new ConcurrentHashMap();//单例池
 
 

而为了实现类的装载和bean的实例化及其维护,ApplicationContext的职责流程是这样的。


(1)加载配置类:这是所有Spring的ApplicationContext都会做的,当然不同的ApplicationContext子类有的是加载xml文件,有的是加载配置类。而我这边是模拟了AnnotationConfigApplicationContext,即加载配置类的方式初始化IOC容器。


(2)扫描注解:在配置类上获取@ComponentScan注解,获取所需要扫描注解的文件路径。这里为了获取所有class文件,用了递归算法扫描。


(3)装载Class文件:对于存在@Component的类进行加载,该类是属于框架维护的


(4)生成BeanDefinition:在所有的类都被加载完之后,对类池中每个类生成对应的BeanDefinition,该对象定义了实例对象Scope范围、是否有代理、是否有别名、切面、是否懒加载等等。


(5)初始化非懒加载的bean:上述步骤都做完了,就对非懒加载且单例的类进行实例化,实例化中遇到类的属性有@Autowired注解,则进行判断(是否有单例对象,是否为框架维护的等),再注入。实例化完成后,则判断是否实现
AopBeanPostProcessor接口,有则进行代理对象的生成。最后在放进单例池进行维护。AopBeanPostProcessor接口就是模拟了Spring的BeanPostProcessor接口,也就是后置处理器,模拟了bean初始化前后进行的操作。

配置类

配置类上实现了@ComponentScan、@Configuration注解,ApplicationContext在初始化时候,会判断该类合法性并加载该类。

@com.CmJava.annotation.Configuration
@ComponentScan("com.CmJava")
public class SpringConfiguration implements Configuration{
}

基本方法

treeFile方法,递归遍历包扫描路径,将扫描到的切面类和bean类维护起来。

    private void treeFile(File[] files, String path, ClassLoader classLoader) {
        if (files.length == 0) {
            return;
        }
        String filePath = "";
        String classPath = "";
        Class<?> aClass = null;
        for (File file : files) {
            if (file.isDirectory()) {
                if (file.listFiles().length > 0) {
                    treeFile(file.listFiles(), path, classLoader);
                }
            } else {
                try {
                    filePath = file.toString().replace("\\", "/");
                    classPath = filePath.substring(filePath.indexOf(path), filePath.indexOf(".class")).replace("/", ".");
                    aClass = classLoader.loadClass(classPath);
                    //获取切面
                    if (aClass.isAnnotationPresent(Aspect.class)) {
                        String pointCut = "";
                        boolean flag = true;
                        List<String> notPointCut = new ArrayList<>();
                        for (Method method : aClass.getDeclaredMethods()) {
                            if (method.isAnnotationPresent(Pointcut.class)) {
                                pointCut = method.getName();
                            } else {
                                String value = methodGetAopAnnotationValue(method);
                                value = value.substring(0, value.indexOf("("));
                                notPointCut.add(value);
                            }
                        }
                        //判断通知和切点的对应关系是否有误
                        for (String notPointCutName : notPointCut) {
                            if (!notPointCutName.equals(pointCut)) {
                                flag = false;
                                break;
                            }
                        }
                        if (flag) {
                            aopClassList.add(aClass);
                        }
                    }

                    //获取框架管理的的class
                    if (aClass.isAnnotationPresent(Component.class)) {
                        classList.add(aClass);
                    }
                } catch (ClassNotFoundException e) {
                    e.printStackTrace();
                }
            }

        }
    }

creatBeanDefinition方法,将上个方法获取到的类进行读取扫描,创建BeanDefinition对象

    private void creatBeanDefinition(List<Class> classList, List<Class> aopClassList, Map<String, BeanDefinition> beanDefinitionMap) {
        String beanName = "";
        Class beanClass = null;
        String scope = "";
        BeanDefinition beanDefinition = null;
        boolean isLazy = false;

        //生成BeanDefinition
        for (Class aClass : classList) {
            if (aClass.isAnnotationPresent(Lazy.class)) {
                isLazy = true;
            } else {
                isLazy = false;
            }
            if (aClass.isAnnotationPresent(Scope.class)) {
                scope = ((Scope) aClass.getAnnotation(Scope.class)).value();
            } else {
                scope = "singleton";
            }
            if (((Component) aClass.getAnnotation(Component.class)).value().equals("")) {
                beanName = aClass.getName();
            } else {
                beanName = ((Component) aClass.getAnnotation(Component.class)).value();
            }

            beanDefinition = new BeanDefinition(beanName, aClass.getName(), aClass, scope, isLazy);
            beanDefinitionMap.put(aClass.getName(), beanDefinition);
        }


        //获取切入点,注入到BeanDefinition
        String access = "";
        String pointCut = "";
        String classString = "";
        String pointCutMethod = "";
        String[] classSplit = null;
        Class beanClassAop = null;
        for (Class aClass : aopClassList) {
            for (Method method : aClass.getDeclaredMethods()) {
                if (method.isAnnotationPresent(Pointcut.class)) {
                    pointCut = method.getAnnotation(Pointcut.class).value();
                    if (pointCutMatch(pointCut)) {
                        pointCut = pointCut.substring(10, pointCut.indexOf("))") + 1);
                        access = pointCut.split(" ")[0];
                        classString = pointCut.split(" ")[1];
                        classSplit = classString.substring(0, classString.lastIndexOf("(..)")).split("\\.");
                        //切点方法
                        pointCutMethod = classSplit[classSplit.length - 1];
                        //切点类全限定名
                        classString = classString.substring(0, classString.indexOf("." + pointCutMethod));


                        if (beanDefinitionMap.containsKey(classString)) {
                            beanClassAop = beanDefinitionMap.get(classString).getBeanClass();
                            if (pointCutMethod.equals("*")) {
                                for (Method method1 : beanClassAop.getDeclaredMethods()) {
                                    beanDefinitionMap.get(classString).getPointCut().put(method1, aClass);
                                    break;
                                }
                            } else {
                                for (Method method1 : beanClassAop.getDeclaredMethods()) {
                                    if (method1.getName().equals(pointCutMethod)) {
                                        beanDefinitionMap.get(classString).getPointCut().put(method1, aClass);
                                        break;
                                    }
                                }
                            }

                        }
                    }
                    break;
                }
            }
        }


    }

instanceNotLazySingletonBean方法,实例化非懒加载的单例bean

private void instanceNotLazySingletonBean(Map<String, BeanDefinition> beanDefinitionMap) {
        BeanDefinition beanDefinition = null;
        Object bean = null;
        String beanName = "";
        for (String beanClassName : beanDefinitionMap.keySet()) {

            beanDefinition = beanDefinitionMap.get(beanClassName);
            if (beanDefinition.getScope().equals("singleton")) {

                if (!singletonExistByClassName(beanClassName)) {

                    bean = doCreateBean(beanClassName);

                    if (!beanDefinition.getBeanName().equals(beanClassName)) {
                        //有bean别名
                        singletonObjects.put(beanDefinition.getBeanName(), bean);
                    } else {
                        //无bean别名
                        singletonObjects.put(beanClassName, bean);
                    }
                }
            }
        }


    }

doCreateBean方法,创建实例化对象

    private Object doCreateBean(String beanClassName) {

        Object bean = null;

        if (beanDefinitionMap.containsKey(beanClassName)) {
            //存在bean定义就创建
            Class beanClass = beanDefinitionMap.get(beanClassName).getBeanClass();
            try {
                //实例化
                bean = beanClass.newInstance();
                //属性填充
                Object fieldObject = null;
                String fieldClassName = "";
                for (Field field : beanClass.getDeclaredFields()) {

                    if (field.isAnnotationPresent(Autowired.class)) {
                        fieldClassName = field.getType().getName();
                        //Autowired注入
                        if (beanDefinitionMap.get(fieldClassName).getPointCut().size()>0){
                            throw new RuntimeException("Autowired未考虑代理对象的注入");
                        }


                        //是否给框架管理
                        if (beanDefinitionMap.containsKey(fieldClassName) || childBeanDefinitionExist(fieldClassName) != null) {

                            if (singletonExistByClassName(fieldClassName)) {
                                //原生对象
                                fieldObject = getSingletonByClassName(fieldClassName);
                            } else {
                                //无对象
                                fieldObject = doCreateBean(fieldClassName);
                                singletonObjects.put(field.getName(), fieldObject);
                            }
                        }else {
                            fieldObject = doCreateBean(fieldClassName);
                        }

                    } else {
                        fieldObject = field.getType().newInstance();
                    }
                    field.setAccessible(true);
                    try {
                        field.set(bean, fieldObject);
                    }catch (Exception e){
                        System.out.println("代理对象不支持Autowire注入");
                        field.set(bean, field.getType().newInstance());
                    }
                }


                //AOP
                if (bean instanceof AopBeanPostProcessor) {
                    //BeanPostProcessor,初始化之前
                    bean = ((AopBeanPostProcessor) bean).postProcessBeforeInitialization(bean, beanClassName);

                    //一些其他的初始化逻辑,就不写了
                    //...

                    //BeanPostProcessor,初始化之后,AOP

                    bean = ((AopBeanPostProcessor) bean).postProcessAfterInitialization(bean, beanClassName, beanDefinitionMap.get(beanClassName).getPointCut());

                }

            } catch (InstantiationException e) {
                e.printStackTrace();
                System.out.println("请确认是否存在有参构造覆盖无参构造的情况");
            } catch (IllegalAccessException e) {
                e.printStackTrace();
                System.out.println("请确认无参构造是否私有");

            }
        } else if (childBeanDefinitionExist(beanClassName) != null) {
            //存在bean子类定义则创建
            BeanDefinition beanDefinition = childBeanDefinitionExist(beanClassName);
            String className = beanDefinition.getBeanClassName();
            if (singletonExistByClassName(className)) {
                bean = getSingletonByClassName(className);
            } else {
                bean = doCreateBean(className);
            }
        } else {
            //框架不管理该bean
            Class<?> aClass = null;
            try {
                aClass = this.getClass().getClassLoader().loadClass(beanClassName);
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
            bean = doCreateBeanNotBySpring(aClass);
        }

        if (bean != null) {
            return bean;
        } else {
            throw new RuntimeException("实例化bean失败");
        }
    }

    /**
     * Autowired非框架管理的bean
     *
     * @param aClass
     * @return
     */
    private Object doCreateBeanNotBySpring(Class<?> aClass) {

        //未完成
        Object bean = null;
        try {
            bean = aClass.newInstance();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }

        return bean;

    }

getBean方法,获取创建好的单例或者返回原型对象

    public Object getBean(String beanClassName) {

        BeanDefinition beanDefinition = beanDefinitionMap.get(beanClassName);
        String beanName = beanDefinition.getBeanName();
        Object bean = null;

        if (beanDefinition.getPointCut().size() > 0) {
            //是个代理对象
            if (beanDefinition.getScope().equals("singleton")) {
                //获取单例对象
                if (singletonExistByProxyClassName(beanClassName)) {
                    //非懒加载
                    bean = singletonObjects.get(beanName);
                } else {
                    //懒加载
                    bean = doCreateBean(beanName);
                    singletonObjects.put(beanName, bean);
                }

            } else if (beanDefinition.getScope().equals("prototype")) {
                //获取原型对象
                bean = doCreateBean(beanName);
            }
        } else {
            //不是代理对象
            if (beanDefinition.getScope().equals("singleton")) {
                //获取单例对象
                if (singletonExistByClassName(beanClassName)) {
                    //非懒加载
                    bean = singletonObjects.get(beanName);
                } else {
                    //懒加载
                    bean = doCreateBean(beanName);
                    singletonObjects.put(beanName, bean);
                }

            } else if (beanDefinition.getScope().equals("prototype")) {
                //获取原型对象
                bean = doCreateBean(beanName);
            }

        }
        return bean;

    }

注解

IOC注解

该框架创建了如下几个IOC注解:

(1)@Autowired:依赖注入,将框架维护的实例对象注入。

(2)@Component:标注为框架维护的bean

(3)@Lazy:懒加载,仅在使用者调用时才创建该类实例

(4)@Scope:bean类型,单例或原型

@Retention(RetentionPolicy.RUNTIME)//运行时生效
@Target({ElementType.FIELD,ElementType.METHOD,ElementType.CONSTRUCTOR})//注解在变量,方法上
public @interface Autowired {

    //beanName
    String value() default "";
}

@Retention(RetentionPolicy.RUNTIME)//运行时生效
@Target(ElementType.TYPE)//注解在类上
public @interface Component {

    //beanName
    String value() default "";
}

//懒加载
@Retention(RetentionPolicy.RUNTIME)//运行时生效
@Target(ElementType.TYPE)//注解在类上
public @interface Lazy {
}

//设置生成bean的模式
@Retention(RetentionPolicy.RUNTIME)//运行时生效
@Target(ElementType.TYPE)//注解在类上
public @interface Scope {

    //默认单例模式
    String value() default "singleton";
}

配置类注解

该框架创建了如下几个配置类注解:

(1)@Configuration:标注配置类。

(2)@ComponentScan:表明框架需要扫描注解的路径

@Retention(RetentionPolicy.RUNTIME)//运行时生效
@Target(ElementType.TYPE)//注解在类上
public @interface Configuration {
}

@Retention(RetentionPolicy.RUNTIME)//运行时生效
@Target(ElementType.TYPE)//注解在类上
public @interface ComponentScan {

    //包路径
    String value() default "";
}

AOP注解

该框架创建了如下几个AOP注解:

(1)@Aspect:标注切面类。

(2)@Pointcut:标注切面类的切点

(3)@Before:前置通知

(4)@After:后置通知

(5)@AfterReturning:最终通知

(6)@AfterThrowing:异常通知

(7)@Around:环绕通知

@Retention(RetentionPolicy.RUNTIME)//运行时生效
@Target(ElementType.TYPE)//注解在类上
public @interface Aspect {
}

@Retention(RetentionPolicy.RUNTIME)//运行时生效
@Target({ElementType.FIELD,ElementType.METHOD,ElementType.CONSTRUCTOR})//注解在变量,方法上
public @interface Pointcut {

    //切入点
    String value();
}

@Retention(RetentionPolicy.RUNTIME)//运行时生效
@Target(ElementType.METHOD)//注解在方法上
public @interface Before {

    //切入点
    String value() default "";
}

@Retention(RetentionPolicy.RUNTIME)//运行时生效
@Target(ElementType.METHOD)//注解在方法上
public @interface After {

    //切入点
    String value() default "";
}

@Retention(RetentionPolicy.RUNTIME)//运行时生效
@Target(ElementType.METHOD)//注解在方法上
public @interface AfterReturning {

    //切入点
    String value() default "";
}

@Retention(RetentionPolicy.RUNTIME)//运行时生效
@Target(ElementType.METHOD)//注解在方法上
public @interface AfterThrowing {

    //切入点
    String value() default "";
}


@Retention(RetentionPolicy.RUNTIME)//运行时生效
@Target(ElementType.METHOD)//注解在方法上
public @interface Around {

    //切入点
    String value() default "";
}

AOP和IOC实现

AOP和IOC实现流程图

如图所示
image

Gitee源码

源码

6

评论区