2021-09-05

Spring加载配置类大概过程

  1. 读取配置类
  2. 扫描配置类,判断配置类中是否包含ComponentScan注解
  3. 根据直接中的路径,以及Spring上下文的类加载器,获取到当前类路径下的文件
  4. 将该路径下的文件进行循环遍历
  5. 判断文件中是否包含Component注解
  6. 如果包含,以beanName为key, BeanDefinition为vlaue,存放到BeanDefinitionMap中。

Spring获取对象的大概过程

  1. 根据传入的beanName,判断beanDefinitionMap中是否存在,如果不存在则抛出异常
  2. 判断该bean是单例还是原型
  3. 如果是单例则去单例池中获取,如果是原型则直接创建。

Spring Aop大概实现过程

  1. 在扫描包,创建Bean之前,会判断该类是否实现BeanPostProcessor这个接口
  2. 如果实现了此接口会将此接口存储到beanPostProcessorList集合中。
  3. 当bean创建完成之后,可以借助**postProcessBeforeInitialization(初始化之前)或者postProcessAfterInitialization(初始化之后)**执行Aop中所需要执行的方法。

加载配置类代码

  1. 创建一个有参构造函数
	public wwhApplicationContext(Class configClass) {
        this.configClass = configClass;

        scan(configClass);

        for (Map.Entry<String, BeanDefinition> entry : beanDefinitionMap.entrySet()) {
            String beanName = entry.getKey();
            BeanDefinition beanDefinition = entry.getValue();
            if (beanDefinition.getScope().equals("singleton")) {
                Object bean = createBean(beanName, beanDefinition);
                singletonObjects.put(beanName, bean);
            }
        }
    }

2.扫描方法

/**
     * 1、解析传进来的class对象,得到扫描路径
     * 2、遍历路径下的所有文件
     * 3、加载每一个文件得到class对象
     * 4、判断是否含有Component注解
     * 5、根据Component注解获取bean的名字,得到一个BeanDefinition对象,存储到BeanDefinitionMap中
     * @param configClass
     */
    private void scan(Class configClass) {
        //扫描配置类,判断配置类中是否有ComponentScan注解
        if (configClass.isAnnotationPresent(ComponentScan.class)) {
            ComponentScan componentScan = (ComponentScan) configClass.getAnnotation(ComponentScan.class);
            String path = componentScan.value();
            path = path.replace(".", "/");

            //通过类加载器获取当前类的路径
            ClassLoader classLoader = wwhApplicationContext.class.getClassLoader();
            URL resources = classLoader.getResource(path);
            //通过类路径获取当前文件夹下的文件
            File file = new File(resources.getFile());
            if (file.isDirectory()) {
                for (File f : file.listFiles()) {
                    String absolutePath = f.getAbsolutePath();

                    absolutePath = absolutePath.substring(absolutePath.indexOf("com"), absolutePath.indexOf(".class"));
                    absolutePath = absolutePath.replace("\\", ".");
                    try {
                        Class<?> clazz = classLoader.loadClass(absolutePath);

                        //如果有Component注解,是一个bean
                        if (clazz.isAnnotationPresent(Component.class)) {
                            Component componentAnnotation = clazz.getAnnotation(Component.class);
                            String beanName = componentAnnotation.value();

                            //判断这个Bean是都实现BeanPostProcessor接口
                            //isAssignableFrom判断的是BeanPostProcessor和clazz是否相同或是另一个类的超类或者接口
                            if (BeanPostProcessor.class.isAssignableFrom(clazz)) {
                                BeanPostProcessor beanPostProcessor = (BeanPostProcessor) clazz.getConstructor().newInstance();
                                beanPostProcessorList.add(beanPostProcessor);
                            }

                            //如果Component注解中未填写bean名称,则借助系统自动生成一个名字
                            if ("".equals(beanName)) {
                                beanName = Introspector.decapitalize(clazz.getSimpleName());
                            }

                            BeanDefinition beanDefinition = new BeanDefinition();
                            beanDefinition.setType(clazz);

                            //判断这个bean是否为单例
                            if (clazz.isAnnotationPresent(Scope.class)) {
                                Scope scopeAnnotation = clazz.getAnnotation(Scope.class);
                                String value =  scopeAnnotation.value();
                                beanDefinition.setScope(value);
                            }else {
                                beanDefinition.setScope("singleton");
                            }


                            beanDefinitionMap.put(beanName, beanDefinition);
                        }
                    } catch (ClassNotFoundException e) {
                        e.printStackTrace();
                    } catch (IllegalAccessException e) {
                        e.printStackTrace();
                    } catch (InstantiationException e) {
                        e.printStackTrace();
                    } catch (NoSuchMethodException e) {
                        e.printStackTrace();
                    } catch (InvocationTargetException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }

3.创建Bean

	private Object createBean( String beanName, BeanDefinition beanDefinition) {
        Class clazz = beanDefinition.getType();
        Object instance = null;
        try {
            instance = clazz.getConstructor().newInstance();

            for (Field field : clazz.getDeclaredFields()) {
                if (field.isAnnotationPresent(Autowired.class)) {
                    field.setAccessible(true);
                    field.set(instance, getBean(field.getName()));
                }
            }

            if (instance instanceof BeanNameAware) {
                ((BeanNameAware) instance).setBeanName(beanName);
            }

            //Bean定义前置处理器,创建每一个Bean的时候都会调用该方法
            for (BeanPostProcessor beanPostProcessor : beanPostProcessorList) {
                //返回代理对象
                instance = beanPostProcessor.postProcessBeforeInitialization(beanDefinition, beanName);
            }

            //如果Bean实现了InitializingBean接口,创建Bean的时候会调用该方法
            //instanceof 判断实例对象,可以判断instance对象是否是InitializingBean类的或接口或其子类接口的实例
            if (instance instanceof InitializingBean) {
                ((InitializingBean) instance).afterPropertiesSet();
            }

            //Bean定义后置处理器,创建每一个Bean的时候都会调用该方法
            for (BeanPostProcessor beanPostProcessor : beanPostProcessorList) {
                //返回代理对象
                instance = beanPostProcessor.postProcessAfterInitialization(beanDefinition, beanName);
            }
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }

        return instance;
    }

4.获取Bean

	public Object getBean(String beanName) {
        //如果在beandefinitionMap中没有,说明传入的beanName是错误的
        if (!beanDefinitionMap.containsKey(beanName)) {
            throw new NullPointerException();
        }

        BeanDefinition beanDefinition = beanDefinitionMap.get(beanName);
        //判断bean是单例的还是原型的
        if (beanDefinition.getScope().equals("singleton")) {
            //如果是单例bean直接去单例池中获取
            Object o = singletonObjects.get(beanName);
            if (o == null) {
                o = createBean(beanName, beanDefinition);
                singletonObjects.put(beanName, o);
            }
            return o;
        } else {
            // 如果是原型,直接创建
            return  createBean(beanName, beanDefinition);
        }
    }
使用python中的pymsql完成如下:表结构与数据创建 1. 建立 `users` 表和 `orders` 表。 `users` 表有用户ID、用户名、年龄字段,(id,name,age) `orders` 表有订单ID、订单日期、订单金额,用户id字段。(id,order_date,amount,user_id) 2 两表的id作为主键,`orders` 表用户id为users的外键 3 插入数据 `users` (1, '张三', 18), (2, '李四', 20), (3, '王五', 22), (4, '赵六', 25), (5, '钱七', 28); `orders` (1, '2021-09-01', 500, 1), (2, '2021-09-02', 1000, 2), (3, '2021-09-03', 600, 3), (4, '2021-09-04', 800, 4), (5, '2021-09-05', 1500, 5), (6, '2021-09-06', 1200, 3), (7, '2021-09-07', 2000, 1), (8, '2021-09-08', 300, 2), (9, '2021-09-09', 700, 5), (10, '2021-09-10', 900, 4); 查询语句 1. 查询订单总金额 2. 查询所有用户的平均年龄,并将结果四舍五入保留两位小数。 3. 查询订单总数最多的用户的姓名和订单总数。 4. 查询所有不重复的年龄。 5. 查询订单日期在2021年9月1日至9月4日之间的订单总金额。 6. 查询年龄不大于25岁的用户的订单数量,并按照降序排序。 7. 查询订单总金额排名前3的用户的姓名和订单总金额。 8. 查询订单总金额最大的用户的姓名和订单总金额。 9. 查询订单总金额最小的用户的姓名和订单总金额。 10. 查询所有名字中含有“李”的用户,按照名字升序排序。 11. 查询所有年龄大于20岁的用户,按照年龄降序排序,并只显示前5条记录。 12. 查询每个用户的订单数量和订单总金额,并按照总金额降序排序。
06-03
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值