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
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSONJSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다. 그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다. 저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.