Spring源码分析(流程梳理)

前言

近期过年,在家待业,想闲着也是闲着,干脆充充电,撸撸Spring的源码玩玩,一提到Spring那么脑子里就会出现IOC和AOP
在这里插入图片描述
首先需要先搞定IOC,IOC先搞懂了,那么理解AOP就更加简单了!

IOC

概要
IOC大部分人都知道是容器,翻译过来是控制反转,也就是将我们手动创建Java对象的工作交给Spring来管理。
在这里插入图片描述
在我们写Java代码时需要new,我们需要什么对象new对象即可,这本身是没有什么问题,但是每次都要new的操作效率低,或者说new这个操作是有我们自己产生的,我们自己来产生这个new的操作,如我们需要10个对象,那么我们就需要new10次,需要100次我们就需要new100次,比较低效,那么我们可以将这个操作交给Spring来完成,那么也就是使用Spring IOC容器来完成。容器就是存放Java对象,也就是Bean,那么这些Bean就是存放在Java一些列的集合,如Map,List等 ,那么这里IOC容器底层实现原理实际上就是反射。通过反射实现@Autowired完成Bean的注入

反射

public class UserService {
    
    
}

public class UserController {
    
    

    private UserService userService;

    public UserService getUserService() {
    
    
        return userService;
    }

    public void setUserService(UserService userService) {
    
    
        this.userService = userService;
    }
}

public class MyTestList {
    
    

    @Test
    public void test() throws Exception {
    
    

        UserController userController=new UserController();
        Class<? extends UserController> clazz = userController.getClass();
        //创建对象
        UserService userService = new UserService();
        System.out.println(userService);
        //获取属性
        Field serviceField = clazz.getDeclaredField("userService");
        serviceField.setAccessible(true);//设置为可访问私有属性
        //只有通过方法才能够设置具体的属性值
        String name = serviceField.getName();
        //拼接方法的名称
        name = name.substring(0, 1).toUpperCase() + name.substring(1, name.length());
        String setMethodName = "set" + name;
        //通过方法注入属性的对象--这里还没注入,只是在构建入参和需要执行的方法
        Method method = clazz.getMethod("setUserService", UserService.class);
        //反射--也就是执行ssetUserService这个方法
        method.invoke(userController, userService);
        System.out.println(userController.getUserService());
    }
}

反射实现@Autowired

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
@Inherited/
@Documented
public @interface MyAutowired {
    
    
}


public class UserService {
    
    
}


public class UserController {
    
    

    @MyAutowired
    private UserService userService;

    public UserService getUserService() {
    
    
        return userService;
    }
}

public class Test2 {
    
    
    public static void main(String[] args)  {
    
    
        UserController userController=new UserController();
        Class<? extends UserController> clazz = userController.getClass();

        获取所有属性,并遍历
        Stream.of(clazz.getDeclaredFields()).forEach(field->{
    
    
            MyAutowired annotation = field.getAnnotation(MyAutowired.class);
            if (annotation!=null){
    
    
                field.setAccessible(true);
                //得到属性的类型
                Class<?> type = field.getType();
                try {
    
    
                    //创建这个属性类型的对象
                    Object o = type.newInstance();
                    //设置属性值
                    field.set(userController,o);
                } catch (InstantiationException e) {
    
    
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
    
    
                    e.printStackTrace();
                }
            }
        });
        System.out.println(userController.getUserService());
    }

}

上面演示两个反射的案例,现在回到IOC这部分,IOC是个容器,能够帮助我们来完成对象的整体创建,创建好之后我们直接在IOC这个容器中获取Java对象就可以了,通俗易懂的IOC就是我们获取具体对象的,这些对象简单的理解是存储在Map中,直接根据key获取Map中的value就可以了, 那么接下来我们看看他是如何将对象创建并存放到IOC中的!下面是大致流程图
在这里插入图片描述

  • 上面xml、annotation这一组泛称BeanDefinition,BeanDefinition描述一个bean实例,该实例具有属性值、构造函数参数值和由具体实现提供的进一步信息。

  • 通过这个BeanDefinitionReader接口将Bean读取到BeanDefinition进行存储

这里读取到Bean的信息后开始实例化,当然Spring不只是一个框架,更是一个生态,为了支撑更加灵活,高效的上层应用,对Spring而言,需要考虑更多的是扩展性,扩展性,扩展性,扩展性导致这里不能简单的直接实例化!

  • Bean的对象创建时通过BeanFunction得到获取到BeanDefinition使用反射来创建的
  • BeanFactoryPostProcessor,这个接口继承后就是来完成扩展操作的,如我们读取到Bean的时候,需要调用某个具体方法,那么我们就可以使用这个接口来完成
  • 实例化和初始化,实例化就是调用对应的构造方法,然后开辟一块内存空间,但是里面的属性都没有完成赋值操作,那么在实例化完成之后需要完成一系列的初始化操作,那么在这实例化—>初始化—>初始化完成的阶段,那么就形成了AOP,其中也包括了BeanPostProcessor这个接口
  • Environment这个接口中封装了一系列的系统环境值,代码中需要获取就直接调用即可

BeanFactory、FactoryBean区别

创建对象有两种方式,一种是BeanFactory,另一种是FactoryBean,一般情况下我们的常规对象都是用BeanFactory来完成创建的,某些特殊的对象,需要定制化的时候那么就需要采用FactoryBean来完成,那么在采用FactoryBean来实现的时候可以使用getObject来定制化处理,想怎么实现就怎么实现,feign就采用这种实现方式

public class MyFactoryBean implements FactoryBean {
    
    
    @Override
    public Object getObject() throws Exception {
    
    
        TestMain testMain = new TestMain();
        System.out.println("----------一系列而外的定制操作-----------");
        //以直接通过getObject方法来完成定制化的Bran,无需使用BeanFactory一步一步按流程生成!
        return testMain;
    }
   
    @Override
    public Class<?> getObjectType() {
    
    
        return null;
    }

    @Override
    public boolean isSingleton() {
    
    
        return true;
    }
}

猜你喜欢

转载自blog.csdn.net/CSDN877425287/article/details/113760260