Análisis de código fuente de Spring (proceso de peinado)

Prefacio

En el reciente Año Nuevo chino, estoy esperando trabajar en casa. Solo quiero estar inactivo. Solo cárguelo y juegue con el código fuente de Spring. Siempre que mencione Spring, IOC y AOP aparecerán en mi mente.
Inserte la descripción de la imagen aquí
Primero, Primero necesito obtener el COI, ¡entonces entender AOP es aún más simple!

COI

Resumen
La mayoría de la gente sabe que IOC es un contenedor, lo que se traduce en inversión de control, lo que significa que creamos manualmente objetos Java para que Spring los administre.
Inserte la descripción de la imagen aquí
Cuando escribimos código Java, necesitamos un nuevo. El tipo de objeto que necesitamos es el nuevo objeto. Esto no es un problema en sí mismo, pero la eficiencia operativa del nuevo cada vez es baja, o la nueva operación la generamos nosotros mismos. nosotros mismos Para generar esta nueva operación, si necesitamos 10 objetos, entonces necesitamos nuevos 10 veces, y si necesitamos 100 veces, necesitamos nuevos 100 veces, lo cual es relativamente ineficiente. Entonces podemos dejar esta operación a Spring para completar, luego use el contenedor Spring IOC para completar. El contenedor es para almacenar objetos Java, es decir, Beans, luego estos Beans se almacenan en una serie de colecciones Java, como Map, List, etc., entonces el principio de implementación subyacente del contenedor IOC es en realidad una reflexión. @Autowired completa la inyección de frijoles a través de la reflexión

reflexión

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());
    }
}

Implementación de reflexión @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());
    }

}

Lo anterior demuestra dos casos de reflexión. Ahora volvamos a la parte IOC. IOC es un contenedor que puede ayudarnos a completar la creación general de objetos. Después de la creación, podemos obtener directamente los objetos Java en el contenedor IOC, que es fácil de entender. IOC Así es como obtenemos objetos específicos. La simple comprensión de estos objetos es que se almacenan en el Mapa, y el valor en el Mapa se puede obtener directamente de acuerdo con la clave. Luego veamos cómo crea y almacena el objeto en el IOC ! A continuación se muestra el diagrama de flujo general
Inserte la descripción de la imagen aquí

  • El grupo anterior de xml y anotación generalmente se llama BeanDefinition. BeanDefinition describe una instancia de bean con valores de atributo, valores de parámetros de constructor e información adicional proporcionada por implementaciones específicas.

  • Lea el Bean BeanDefinitionpara su almacenamiento a través de esta interfaz BeanDefinitionReader

Después de leer la información del Bean, comenzamos a crear una instancia. Por supuesto, Spring no es solo un marco, sino también una ecología. Para admitir aplicaciones de capa superior más flexibles y eficientes, para Spring, debemos considerar más escalabilidad y extensibilidad. ¡La extensibilidad y la extensibilidad hacen que sea imposible simplemente crear una instancia directamente aquí!

  • Cuando se crea el objeto Bean, se crea BeanFunctionobteniendo BeanDefinition y utilizando la reflexión.
  • BeanFactoryPostProcessor, Esta interfaz se hereda para completar la operación de expansión. Por ejemplo, cuando leemos el Bean, necesitamos llamar a un método específico, luego podemos usar esta interfaz para completar
  • 实例化和初始化, La instanciación es llamar al método de construcción correspondiente y luego abrir un espacio de memoria, pero las propiedades en el interior no han completado la operación de asignación, luego, una vez que se completa la instanciación, es necesario completar una serie de operaciones de inicialización y luego crear una instancia aquí: > inicializar—> Cuando se completa la inicialización, se forma AOP, que también incluye BeanPostProcessoresta interfaz
  • EnvironmentEn esta interfaz se encapsula una serie de valores del entorno del sistema y puede llamarlos directamente si necesita incluirlos en el código.

Diferencia entre BeanFactory y FactoryBean

Hay dos formas de crear objetos, una es BeanFactory y la otra es FactoryBean. En general, nuestros objetos regulares se crean con BeanFactory. Para algunos objetos especiales, FactoryBean es necesario cuando se requiere personalización. Para completar, puede usar getObject para Personalice el procesamiento cuando use FactoryBean para implementarlo, e impleméntelo como desee, y fingir utiliza este método de implementación.

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;
    }
}

Supongo que te gusta

Origin blog.csdn.net/CSDN877425287/article/details/113760260
Recomendado
Clasificación