首页 > 其他分享 >手写Spring底层机制

手写Spring底层机制

时间:2024-04-09 11:57:42浏览次数:15  
标签:Spring Object clazz instance bean new 手写 beanDefinition 底层

手写Spring底层机制

IOC容器

    //定义 BeanDefinitionMap 存放 beanDefinition
    private ConcurrentHashMap<String,BeanDefinition> beanDefinitionMap =
            new ConcurrentHashMap<>();

    //定义 singletonObjects 存放 单例
    private ConcurrentHashMap<String,Object> singletonObjects =
            new ConcurrentHashMap<>();


    //定义beanPostProcessorList 存放 BeanPostProcessor
    private ArrayList<BeanPostProcessor> beanPostProcessorList=
            new ArrayList<>();


构造器

//构造器
public ZyApplicationContext(Class configClass) {
    this.configClass = configClass;

    beanDefinitionsByScan();

    //初始化单例池
    initSingletonObjects();
}

扫描包

private void beanDefinitionsByScan() {
        //获得扫描的包
        ComponentScan componentScan =
                (ComponentScan)this.configClass.getDeclaredAnnotation(ComponentScan.class);

        //获取路径
        String path = componentScan.value();

        path = path.replace(".","/");
        //获取工作路径
        ClassLoader classLoader = ZyApplicationContext.class.getClassLoader();

        URL resource = classLoader.getResource(path);

        File file = new File(resource.getFile());
        if (file.isDirectory()){
            File[] files = file.listFiles();
            for (File f : files) {
                //获取绝对路径
                String fileAbsolutePath = f.getAbsolutePath();
                if (fileAbsolutePath.endsWith(".class")) {
                    //获取className
                    String className = fileAbsolutePath.substring(fileAbsolutePath.lastIndexOf("\\") + 1, fileAbsolutePath.indexOf(".class"));

                    String fullPath = path.replace("/", ".") + "." + className;

                    try {
                        Class<?> clazz = classLoader.loadClass(fullPath);
                        if (clazz.isAnnotationPresent(Component.class)) {

                            //初始化beanPostProcessorList
                            if (BeanPostProcessor.class.isAssignableFrom(clazz)){
                              BeanPostProcessor beanPostProcessor =
                                      (BeanPostProcessor)clazz.newInstance();
                                beanPostProcessorList.add(beanPostProcessor);
                                continue;
                            }


                            //处理className
                            String value = clazz.getDeclaredAnnotation(Component.class).value();
                            if ("".equals(value)){
                                className = StringUtils.uncapitalize(className);
                            }else {
                                className = value;
                            }
                            System.out.println("是一个bean 类名= " + className);
                            //设置 beanDefinition
                            BeanDefinition beanDefinition = new BeanDefinition();
                            //设置scope
                            if (clazz.isAnnotationPresent(Scope.class)){
                                beanDefinition.setScope(clazz.getDeclaredAnnotation(Scope.class).value());
                            }else{
                                beanDefinition.setScope("singleton");
                            }
                            beanDefinition.setClazz(clazz);

                            //放入 beanDefinitionMap
                            beanDefinitionMap.put(className,beanDefinition);




                        } else {
                            System.out.println("不是一个bean 类名= " + className);
                        }
                    } catch (Exception e) {
                        throw new RuntimeException(e);
                    }
                }
            }
        }
    }

初始化单例池

private void initSingletonObjects() {
        Enumeration<String> keys = beanDefinitionMap.keys();
        while (keys.hasMoreElements()){
            String beanName = keys.nextElement();
            BeanDefinition beanDefinition = beanDefinitionMap.get(beanName);
            String scope = beanDefinition.getScope();
            if ("singleton".equals(scope)){
                Object bean = createBean(beanDefinition,beanName);
                singletonObjects.put(beanName,bean);
            }

        }
    }

getBean()

 public Object getBean(String name){
        if (beanDefinitionMap.containsKey(name)){
            BeanDefinition beanDefinition = beanDefinitionMap.get(name);
            String scope = beanDefinition.getScope();
            if ("singleton".equals(scope)){
                return singletonObjects.get(name);
            }else{
                return createBean(beanDefinition,name);
            }
        }
        return null;
    }

createBean()

 private Object createBean(BeanDefinition beanDefinition,String beanName){
        try {
            Class clazz = beanDefinition.getClazz();
            Object instance = clazz.getDeclaredConstructor().newInstance();
            
            return instance;
        } catch (InstantiationException e) {
            throw new RuntimeException(e);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        } catch (InvocationTargetException e) {
            throw new RuntimeException(e);
        } catch (NoSuchMethodException e) {
            throw new RuntimeException(e);
        }
    }

依赖注入

  • 加入到createBean()中

  private Object createBean(BeanDefinition beanDefinition,String beanName){
        try {
            Class clazz = beanDefinition.getClazz();
            Object instance = clazz.getDeclaredConstructor().newInstance();

            //依赖注入
            Field[] declaredFields = clazz.getDeclaredFields();
            for (Field declaredField : declaredFields) {
                if (declaredField.isAnnotationPresent(Autowired.class)){
                    if (declaredField.getDeclaredAnnotation(Autowired.class).required()){
                        //获的字段名
                        String fieldName = declaredField.getName();
                        //获取实例
                        Object bean = getBean(fieldName);
                        declaredField.setAccessible(true);
                        declaredField.set(instance,bean);
                    }
                }
            }

          
            return instance;
        } catch (InstantiationException e) {
            throw new RuntimeException(e);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        } catch (InvocationTargetException e) {
            throw new RuntimeException(e);
        } catch (NoSuchMethodException e) {
            throw new RuntimeException(e);
        }
    }

后置处理器

  • 加入到createBean()中

  private Object createBean(BeanDefinition beanDefinition,String beanName){
        try {
            Class clazz = beanDefinition.getClazz();
            Object instance = clazz.getDeclaredConstructor().newInstance();

            //依赖注入
            Field[] declaredFields = clazz.getDeclaredFields();
            for (Field declaredField : declaredFields) {
                if (declaredField.isAnnotationPresent(Autowired.class)){
                    if (declaredField.getDeclaredAnnotation(Autowired.class).required()){
                        //获的字段名
                        String fieldName = declaredField.getName();
                        //获取实例
                        Object bean = getBean(fieldName);
                        declaredField.setAccessible(true);
                        declaredField.set(instance,bean);
                    }
                }
            }

            //后置处理器 before()
            //遍历 beanPostProcessorList
            for (BeanPostProcessor beanPostProcessor : beanPostProcessorList) {
                Object current = beanPostProcessor.
                        postProcessBeforeInitialization(instance, beanName);
                if (current!=null){
                    instance = current;
                }

            }


            //初始化bean
            if (instance instanceof InitializingBean){
                try {
                    ((InitializingBean)instance).afterPropertiesSet();
                } catch (Exception e) {
                    throw new RuntimeException(e);
                }
            }



            //后置处理器 after()
            //遍历 beanPostProcessorList
            for (BeanPostProcessor beanPostProcessor : beanPostProcessorList) {
                Object current = beanPostProcessor.
                        postProcessAfterInitialization(instance, beanName);
                if (current!=null){
                    instance = current;
                }

            }


            System.out.println("");
            System.out.println("-------------------------------------");
            System.out.println("");
            return instance;
        } catch (InstantiationException e) {
            throw new RuntimeException(e);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        } catch (InvocationTargetException e) {
            throw new RuntimeException(e);
        } catch (NoSuchMethodException e) {
            throw new RuntimeException(e);
        }
    }

AOP

  • AOP需要在后置处理器的before方法中实现

 @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) {
        System.out.println("ZyBeanPostProcessor后置处理器-After-beanName= "+beanName);


        //aop实现

        if("smartDog".equals(beanName)) {
            Object proxyInstance = Proxy.newProxyInstance(ZyBeanPostProcessor.class.getClassLoader(), bean.getClass().getInterfaces(), new InvocationHandler() {


                @Override
                public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                    Object result = null;

                    if ("getSum".equals(method.getName())) {
                        SmartAnimalAspect.showBeginLog();
                        result = method.invoke(bean, args);
                        SmartAnimalAspect.showBeginLog();
                    }else {
                        result = method.invoke(bean, args);//执行目标方法
                    }

                    return result;
                }
            });
            return proxyInstance;
        }

        return bean;
    }

几个Spring的问题

1.单例/多例怎么实现的?@scope为什么可以实现?

回答:@scope 的value属性可以设置为singleton /prototype

通过getBean()方法 如果bean中的属性scope为singleton 就从单例池直接拿,如果是prototype 就调用createBean()创建一个实例

2.如何实现依赖注入?@Autowired Spring容器如何实现依赖注入?

回答: 遍历clazz的所有属性 通过@Autowired注解 如果有 先获取字段名 再通过getBean()获取对应的bean 最后用filed.set()方法将实例的该属性设置为 获取到的bean 实现依赖注入

3.后置处理器 为什么在创建bean 时 调用bean 的 init方法初始化前/后 调用?

//后置处理器 before()
            //遍历 beanPostProcessorList
            for (BeanPostProcessor beanPostProcessor : beanPostProcessorList) {
                Object current = beanPostProcessor.
                        postProcessBeforeInitialization(instance, beanName);
                if (current!=null){
                    instance = current;
                }

            }


            //初始化bean
            if (instance instanceof InitializingBean){
                try {
                    ((InitializingBean)instance).afterPropertiesSet();
                } catch (Exception e) {
                    throw new RuntimeException(e);
                }
            }



            //后置处理器 after()
            //遍历 beanPostProcessorList
            for (BeanPostProcessor beanPostProcessor : beanPostProcessorList) {
                Object current = beanPostProcessor.
                        postProcessAfterInitialization(instance, beanName);
                if (current!=null){
                    instance = current;
                }

            }

4.后置处理器和AOP有什么关系,Spring Aop如何实现??

回答:aop的实现实在后置处理器的before中实现的,底层使用动态代理

 //aop实现

        if("smartDog".equals(beanName)) {
            Object proxyInstance = Proxy.newProxyInstance(ZyBeanPostProcessor.class.getClassLoader(), bean.getClass().getInterfaces(), new InvocationHandler() {


                @Override
                public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                    Object result = null;

                    if ("getSum".equals(method.getName())) {
                        SmartAnimalAspect.showBeginLog();
                        result = method.invoke(bean, args);
                        SmartAnimalAspect.showBeginLog();
                    }else {
                        result = method.invoke(bean, args);//执行目标方法
                    }

                    return result;
                }
            });
            return proxyInstance;
        }

        return bean;

标签:Spring,Object,clazz,instance,bean,new,手写,beanDefinition,底层
From: https://www.cnblogs.com/zydevelop/p/18122497/zy_springbottom

相关文章

  • 史上最全最强SpringMVC详细示例实战教程
    一、SpringMVC基础入门,创建一个HelloWorld程序1.首先,导入SpringMVC需要的jar包。2.添加Web.xml配置文件中关于SpringMVC的配置123456789101112131415<!--configurethesettingofspringmvcDispatcherServletandconfigurethemapping-->......
  • Spring之代理模式
    目录前言为什么需要代理呢?  JDK动态代理方法一:方法二: 通用代理对象实现 CGLIB代理1.什么是CGLIB呢?2.与JDK代理有什么区别呢?3.项目建立4.CGLIB常用API前言   在Spring框架中,代理是一种用于实现AOP(Aspect-OrientedProgramming,面向切面编程)和声明式......
  • 基于Java+SpringBoot+Vue前后端分离大学生校园兼职求职招聘信息系统(适合毕业设计项目
    文章目录目录前言一、系统设计1、系统运行环境2.系统架构设计二、系统核心技术三.系统功能实现四.实现代码五.源码获取前言 本文旨在探讨并设计一个基于Springboot框架的大学生校园兼职求职招聘信息系统。该系统的设计与实现,旨在满足大学生寻找兼职工作的......
  • SpringBoot——测试
    SpringBoot测试源码在test-springboot测试无非就是设定预期值与真实值比较,相同则测试通过,不同则测试失败Ctrl+鼠标左键看源码,再按ctrl:f12查看方法0、环境<?xmlversion="1.0"encoding="UTF-8"?><projectxmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://ww......
  • SpringBoot集成jasypt,加密yml配置文件
    一、Jasypt简介Jasypt是一个Java简易加密库,用于加密配置文件中的敏感信息,如数据库密码。jasypt库与springboot集成,在实际开发中非常方便。1、JasyptSpringBoot为springboot应用程序中的属性源提供加密支持,出于安全考虑,Springboot配置文件中的敏感信息通常需要对它进......
  • springboot本地打war包
    1、pom.xml修改图里标注的①②,新增③,图片下面有我打包的pom.xml大家可以参考<?xmlversion="1.0"encoding="UTF-8"?><projectxmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:s......
  • Set集合以及其中实现类的底层原理分析
    Set集合的特点无序:存取顺序不一致如存入张三、李四、王五。而遍历获取到的是李四,张三,王五不重复:可以去除重复无索引:没有带索引的方法,所以不能使用普通for循环遍历,也不能通过索引来获取元素set集合的实现类HashSet:无序、不重复、无索引LinkedHashSet:有序、不重复、无索......
  • 「Java开发指南」如何利用MyEclipse启用Spring DSL?(一)
    本教程将引导您通过启用SpringDSL和使用ServiceSpringDSL抽象来引导Spring和Spring代码生成项目,本教程中学习的技能也可以很容易地应用于其他抽象。在本教程中,您将学习如何:为SpringDSL初始化一个项目创建一个模型包创建一个服务和操作实现一个服务方法启用JAX-WS和DWR......
  • 基于SpringBoot+MySQL+SSM+Vue.js的生鲜在线销售系统(附论文)
    演示视频基于SpringBoot+MySQL+SSM+Vue.js的生鲜在线销售系统技术描述开发工具:Idea/Eclipse数据库:MySQLJar包仓库:Maven前端框架:Vue/ElementUI后端框架:Spring+SpringMVC+Mybatis+SpringBoot文字描述基于SpringBoot+MySQL+SSM+Vue.js的生鲜在线销售系统(附......
  • 基于SpringBoot+MySQL+SSM+Vue.js的招聘系统(附论文)
    演示视频基于SpringBoot+MySQL+SSM+Vue.js的招聘系统技术描述开发工具:Idea/Eclipse数据库:MySQLJar包仓库:Maven前端框架:Vue/ElementUI后端框架:Spring+SpringMVC+Mybatis+SpringBoot文字描述基于SpringBoot+MySQL+SSM+Vue.js的招聘系统(附论文),用户,管理员......