Spring - 원리 해석 - 반사 와 주 해 를 이용 하여 IoC 의 자동 조립 을 모 의 합 니 다.

Spring 을 분석 하 는 IoC 용기 가 주 해 를 바탕 으로 하 는 자동 조립 (자동 주입 의존) 의 원리
1. 본 사례 는 주석 과 반사 체 제 를 사용 하여 Spring 에서 IoC 의 자동 조립 기능 을 모 의 하여 두 개의 주 해 를 정의 합 니 다. @ Component 는 구성 요 소 를 표시 합 니 다. @Autowired, 짜 여야 할 속성 을 표시 합 니 다.모든 구성 요 소 를 스 캔 하기 위해 @ Component 주석 처리 장 치 를 정의 합 니 다.구성 요 소 를 예화 하기 위해 bean 공장 을 정의 합 니 다.테스트: 두 개의 구성 요소 가 있 습 니 다. 한 구성 요 소 는 다른 구성 요소 의 속성 에 설정 되 어 있 습 니 다.2. 주 해 를 정의 합 니 다 2.1. 정의 @ Component 주 해 는 표 시 된 구성 요소 가 용기 에 의 해 자동 으로 스 캔 되 고 인 스 턴 스 를 만 듭 니 다.
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
 
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Component {
    public String id();
}

주해 의 정 의 는 인터페이스의 정의 주해 정의 와 유사 하 다
public @interface Component {
}

인터페이스 정의
public interface Component {
}

차이 점 은 인터페이스 라 는 식별 자 앞 에 @ 기호 가 있 는 지 없 는 지 에 있 을 뿐이다.
그리고 주해 의 정 의 는 몇 개의 원생 주해 에 도 사용 해 야 합 니 다.
@Target(ElementType.TYPE)

이 주 해 는 사용자 정의 주해 Component 가 누 구 를 표시 하 는 데 사용 되 는 지 보 여 줍 니 다. 그 중에서 Element Type. TYPE 는 이 주 해 를 사용 하여 유형 을 표시 할 수 있 습 니 다. 즉, 클래스, 인터페이스 등 을 표시 할 수 있 습 니 다.필드, 방법 등 을 표시 하 는 FIELD, METHOD 등 도 있다.
@Retention(RetentionPolicy.RUNTIME)

이 사용자 정의 주 해 를 언제 까지 유지 해 야 하 는 지 를 표시 합 니 다. 원본 코드 에 만 저장 하면 컴 파일 후 없습니다.실행 할 때 까지 보류 하거나 실행 할 때 도 계속 있 습 니 다.실행 중 으로 설정 되 어 있 습 니 다.그리고 이 주해 에는 다음 줄 이 있 습 니 다.
public String id();

인터페이스 에 있 는 방법 과 비슷 한 성명 이 있 습 니 다. 그러나 주해 에 서 는 주해 의 속성 을 표시 합 니 다. 나중에 사용 할 때 어떻게 사용 하 는 지 보면 알 수 있 습 니 다.2.2. 정의 @ Autowired 주해 이 주 해 는 구성원 변 수 를 위 한 주해 입 니 다. 이 주 해 를 사용 하면 이 필드 는 프로그램 에서 값 을 부여 해 야 합 니 다.
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
 
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Autowire {
    public String id();

}

 
3. Beanfactory (즉, 주해 프로세서) 의 사용자 정의 주 해 를 정의 한 후에 실제 적 으로 쓸모 가 없습니다.주해 가 쓸모 를 발휘 하려 면 주해 프로세서 에 중점 을 두 어야 한다.우선 이 프로세서 가 그런 일 을 했 는 지 명 확 히 하 겠 습 니 다. 먼저 주어진 구성 요소 의 가방 이름 에 따라 이 가방 을 스 캔 하여 @ Component 주석 에 표 시 된 모든 종 류 를 찾 아 유형의 정 보 를 저장 합 니 다.그리고 getBean () 방법 을 제공 하여 bean 의 id 에 따라 bean 을 가 져 올 수 있 습 니 다.다음은 이 빈 팩 토리 가 어떻게 작 성 됐 는 지 살 펴 보 겠 습 니 다.
3.1.BeanFactory.java
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
 
public class BeanFactory {
 
    private HashMap beanPool;
    private HashMap components;
    
    public BeanFactory(String packageName) {
        beanPool = new HashMap<>();
        
        scanComponents(packageName);
    }
    
    private void scanComponents(String packageName) {
        components = ComponentScanner
                .getComponentClassName(packageName);
    }
    
    public Object getBean(String id) throws ClassNotFoundException, 
            InstantiationException, IllegalAccessException, 
            NoSuchMethodException, SecurityException, 
            IllegalArgumentException, InvocationTargetException {
        
        if (beanPool.containsKey(id)) {
            return beanPool.get(id);
        }
        
        if (components.containsKey(id)) {
        
            Object bean = Class.forName(components.get(id))
                    .newInstance();
            
            bean = assemblyMember(bean);
            
            beanPool.put(id, bean);
            
            return getBean(id);
        }
        
        throw new ClassNotFoundException();
    }
    
    private Object assemblyMember(Object obj) throws 
            ClassNotFoundException, InstantiationException, 
            IllegalAccessException, NoSuchMethodException, 
            SecurityException, IllegalArgumentException, 
            InvocationTargetException {
        
        Class cl = obj.getClass();
        
        for (Field f : cl.getDeclaredFields()) {
            Autowire at = f.getAnnotation(Autowire.class);
            
            if (at != null) {
 
                Method setMethod = cl.getMethod("set" 
                        + captureName(f.getName()), f.getType());
                        
                setMethod.invoke(obj, getBean(at.id()));
            }
        }
        return obj;
    }
    
    public static String captureName(String name) {
        char[] cs=name.toCharArray();
        cs[0]-=32;
        return String.valueOf(cs);
    }

}

 
 
3.2. Component Scann. 자바 라 는 BeanFactory 는 구조 함수 에서 하나의 클래스 를 사용 하여 가방 에 있 는 모든 종류의 정 보 를 검색 합 니 다.
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
 
public class ComponentScanner {
 
    public static HashMap getComponentClassName(
            String packageName) {
        List classes = getClassName(packageName);
        HashMap components = new HashMap();
        
        try {
            
            for (String cl : classes) {
                cl = cl.replace("workspace_java.LearningJava.bin.", "");
                
                Component comp = Class.forName(cl).getAnnotation(Component.class);
                
                if (comp != null) {
                    components.put(comp.id(), cl);
                }
            }
        
        } catch (ClassNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        
        return components;
    }
    
    public static List getClassName(String packageName) {
        String filePath = ClassLoader.getSystemResource("").getPath() 
                + packageName.replace(".", "\\");  
        List fileNames = getClassName(filePath, null);
        return fileNames;
    }
    
    private static List getClassName(String filePath
            , List className) {  
        List myClassName = new ArrayList();  
        File file = new File(filePath);  
        File[] childFiles = file.listFiles();  
        for (File childFile : childFiles) {  
            if (childFile.isDirectory()) {  
                myClassName.addAll(getClassName(childFile.getPath()
                        , myClassName));  
            } else {  
                String childFilePath = childFile.getPath();  
                childFilePath = childFilePath.substring(childFilePath
                        .indexOf("\\classes") + 9, childFilePath.lastIndexOf("."));  
                childFilePath = childFilePath.replace("\\", ".");  
                myClassName.add(childFilePath);  
            }  
        }  
  
        return myClassName;  
    }
    
    public static void main(String[] args) {
        getComponentClassName("com.oolong.javase.annotation");
    }

}

 
4. 테스트
아 날로 그 데이터베이스 접근 인 터 페 이 스 를 정의 합 니 다.
@Component(id = "dataAccessInterface")
public class DataAccessInterface {
 
    public String queryFromTableA() {
        return "query result";
    }
}

이 종 류 는 Component 라 는 주 해 를 사 용 했 고 이 주해 의 id 속성 을 사 용 했 습 니 다.아 날로 그 업무 인 터 페 이 스 를 정의 합 니 다.
@Component(id="businessObject")
public class BusinessObject {
 
    @Autowire(id="dataAccessInterface")
    private DataAccessInterface dai;
    
    public void print() {
        System.out.println(dai.queryFromTableA());
    }
    
    public void setDai(DataAccessInterface dai) {
        this.dai = dai;
    }
}

이 인 터 페 이 스 는 @ Component 라 는 주석 표 시 를 사용 하 는 것 외 에 도 구성원 변수 가 있 습 니 다. Autowire 라 는 주석 표 시 를 사 용 했 습 니 다.이 주석 표 시 를 사용 하면 이 멤버 변수의 초기 화 는 빈 팩 토리 에 맡 길 것 임 을 표시 합 니 다.
테스트
public class BeanFactoryTester {
 
    public static void main(String[] args) {
        BeanFactory beanFactory = new BeanFactory("com.oolong.javase.annotation");
        
        BusinessObject obj = (BusinessObject) beanFactory.getBean("businessObject");
        obj.print();
            
    }

}

빈 팩 토 리 를 사용 하여 비 즈 니스 Object 의 대상 을 만 든 후 이 대상 의 print 방법 을 사용 하여 결 과 를 출력 합 니 다.이러한 정의 로 돌아 가면 다음 과 같은 것 을 볼 수 있 습 니 다.
public void print() {
    System.out.println(dai.queryFromTableA());
}

이 방법 은 멤버 변수 dai 의 query FromTablea 방법 을 호출 합 니 다.이 클래스 에 서 는 이 구성원 변수의 성명 만 있 고 할당 이 없습니다.
이 할당 은 또 어디에서 진행 되 었 습 니까?
이것 이 바로 우리 가 작성 한 이 빈 팩 토리 가 집행 한 것 이다.주해 와 반사 메커니즘 을 통 해 자동 으로 클래스 에 의존 을 주입 한다.
 
다음으로 전송:https://www.cnblogs.com/weilu2/p/spring_ioc_analysis_principle_bsici_on_reflection_annotation.html

좋은 웹페이지 즐겨찾기