> Java > java지도 시간 > SpringBoot가 리플렉션을 사용하여 IOC 및 getBean을 시뮬레이션하는 방법

SpringBoot가 리플렉션을 사용하여 IOC 및 getBean을 시뮬레이션하는 방법

王林
풀어 주다: 2023-05-30 09:25:12
앞으로
1055명이 탐색했습니다.

Spring 기본 아이디어 IOC

두 번째는 Java 리플렉션입니다. 리플렉션 메커니즘은 Spring의 중요한 구현 핵심입니다. 오늘 순환 참조 문제를 해결하기 위해 Spring의 3단계 캐시를 살펴보면서 Bean의 생명주기를 발견했습니다. 그리고 Java 객체의 생성 과정은 유사도가 높기 때문에 Bean 생성 과정을 살펴보고 처음부터 Bean 인스턴스를 생성하는 과정이 Spring에서 매우 우아한 코드를 사용하여 리플렉션을 사용하여 구현된다는 사실을 발견했습니다. 그리고 다양한 맵 데이터 구조. 빈의 파이프라인 생성이 매우 우아하기 때문에 리플렉션을 사용하여 인스턴스 객체를 역으로 생성하는 가젯을 작성해 보았습니다.

그러면 객체 생성 과정을 미리 이해해야 합니다.

객체 생성 과정을 다음과 같이 요약합니다.

상수 풀에 객체에 대한 기호 참조가 있는지 확인하고 다음 단계를 거쳤는지 확인합니다. 클래스 로딩 프로세스가 없으면 클래스 로딩 프로세스를 수행합니다.

새 개체에 대한 메모리 할당(두 가지 방법: 포인터 충돌 및 사용 가능 목록) 및 삭제 개체 헤더 외부의 다른 메모리 공간은 W를 0으로 할당했습니다.

객체 헤더를 설정하세요.

객체 초기화는 생성자 메서드를 실행하고 정의하려는 값을 필요한 필드에 할당하는 프로세스입니다.

세부 사항 추가: 새로운 객체에 대한 메모리 할당 과정에서 우선 클래스 로딩이 완료된 후 객체에 필요한 메모리 크기가 완전히 결정됩니다. 메모리 할당 과정은 실제로 동일한 크기의 블록을 분할하는 것입니다. Java 힙에 메모리를 제공하지만 어떻게 나눌까요? Java 힙의 메모리 레이아웃이 엄격한 순서로 할당되면, 즉 한쪽은 사용되고 다른 쪽은 비어 있으면 포인터 충돌에 의해 메모리가 할당됩니다. 소위 포인터는 구분선에 수집됩니다. 여유 영역과 사용 영역 사이 메모리가 필요한 경우 이동에 포함된 길이가 Java 개체에 필요한 메모리 크기와 같아질 때까지 포인터가 뒤로 이동한 후 중지되고 할당됩니다. 하지만 Java 힙의 메모리 레이아웃이 단편화되고 불연속적이라면 어떻게 될까요? 우리는 모든 Java 힙 프리 영역의 크기와 위치 정보를 기록하는 목록만 유지 관리할 수 있습니다. 할당 시 새 객체에 가장 적합한 영역 할당만 찾으면 됩니다.

가비지 수집기의 기능과 공간 압축을 수행할 수 있는지 여부에 따라 Java 힙이 일반인지 여부가 결정됩니다. 우리가 사용하는 컬렉터가 Serial과 Parnew인 경우 포인터 충돌로 인해 할당됩니다. CMS 가비지 컬렉터를 사용할 때는 번거로운 여유 영역 테이블 할당을 사용해야 합니다.

여기서 우리는 속성과 메서드를 채우는 데 중점을 둡니다. 개체의 영혼은 개체의 속성과 메서드입니다.

전체 도구에서 사용되는 핵심 속성:

    private static volatile Constructor<?> constructor;
    private static volatile Object newInstance;
    private static volatile Map<String, Method> methodMap;
로그인 후 복사

먼저 이 메서드의 기능을 살펴보겠습니다.

  public static Constructor<?> getConstructor(Object dataType) {
        Class<?> typeClass = dataType.getClass();
        try {
            Constructor<?> constructor = typeClass.getConstructor();
            constructor.setAccessible(true);
            return constructor;
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
            return null;
        }
    }
로그인 후 복사

유형의 생성자를 가져옵니다. 이는 매개변수 없는 구성이라는 점에 유의하세요. 매개변수 없는 구성이 없으면 해당 구성에 속성이 몇 개 있는지 모르기 때문에 오류가 발생할 수 있습니다. ? (우리는 리버스 엔지니어링이라는 점을 항상 기억하세요!! ! 이 유형에 무엇이 있는지 모르겠습니다! ! 모든 것이 반영된 정보입니다.)

public static void fillValueToNewInstance(Object dataType, Map<String, Object> initialMap) throws Exception {
        constructor = getConstructor(dataType);
        Class<?> typeClass = dataType.getClass();
        Field[] declaredFields = typeClass.getDeclaredFields();
        Iterator<Field> fieldIterator = Arrays.stream(declaredFields).iterator();
        newInstance = constructor.newInstance();
        while (fieldIterator.hasNext()) {
            Field field = fieldIterator.next();
            field.setAccessible(true);
            if (initialMap != null)
                field.set(newInstance, initialMap.get(field.getName()));
        }
    }
로그인 후 복사

여기에 속성을 가져와서 입력하세요.

 public static Method[] getMethodArray(Object dataType) {
        return dataType.getClass().getDeclaredMethods();
    }
로그인 후 복사

모든 메소드를 가져와서 메소드 배열을 형성하세요.

  public static void fillMethodMap(Object dataType) {
        methodMap = new HashMap<>();
        Method[] methodArray = getMethodArray(dataType);
        Iterator<Method> iterator = Arrays.stream(methodArray).iterator();
        while (iterator.hasNext()) {
            Method method = iterator.next();
            method.setAccessible(true);
            methodMap.put(method.getName(), method);
        }
    }
로그인 후 복사

메소드를 메소드 컬렉션에 저장하여 보관하세요.

 public static Object useMethod(String methodName, @Nullable Object... parameters) throws Exception {
        return methodMap.get(methodName).invoke(newInstance, parameters);
    }
로그인 후 복사

사용 방법은 이름을 전달하는 것입니다.

    @SneakyThrows
    public static Object getBean(Object dataType, Map<String, Object> parameterMap) {
        fillValueToNewInstance(dataType, parameterMap);
        fillMethodMap(dataType);
        return newInstance;
    }
로그인 후 복사

getBean 메소드.

  public static void main(String[] args) throws Exception {
        Map<String,Object> map = new HashMap<>();
        map.put("name","xu");
        map.put("age",Integer.valueOf(18));
        map.put("sex",&#39;女&#39;);
        Person bean = (Person) getBean(new Person(), map);
        System.out.println(bean.toString());
        System.out.println(useMethod("toString"));
    }
로그인 후 복사

테스트 방법. 유형 정보는 다음과 같습니다.

class Person {
    private String name;
    private Integer age;
    private Character sex;
    //无参构造绝对不能少
    public Person() {
    }
    @Override
    public String toString() {
        return "Person{" +
                "name=&#39;" + name + &#39;\&#39;&#39; +
                ", age=" + age +
                ", sex=" + sex +
                &#39;}&#39;;
    }
}
로그인 후 복사

테스트 결과는 다음과 같습니다.

SpringBoot가 리플렉션을 사용하여 IOC 및 getBean을 시뮬레이션하는 방법

여기에서는 Person person = new Person();을 사용하여 객체를 인스턴스화하지 않고 리플렉션을 사용하여 객체를 인스턴스화했습니다.

여기에 사용된 반사 방법을 나열하겠습니다.

getDeclaredFields 도메인 속성 개체 가져오기

getName 속성 이름 가져오기

getType 속성 유형의 바이트코드 파일 가져오기

setAccessible(true) 무차별 대입 크래킹 설정 그리고 속성의 비공개 사용을 가져옵니다

getDeclaredMethods 모든 메소드 배열 가져오기

getClass 바이트코드 파일 가져오기

getConstructor 매개변수 없는 생성자 가져오기

위 내용은 SpringBoot가 리플렉션을 사용하여 IOC 및 getBean을 시뮬레이션하는 방법의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

관련 라벨:
원천:yisu.com
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿