스프링 IOC 프로토 타입
스프링 프레임 워크의 기본 코어 및 시작점은 의심 할 여지없이 IOC입니다. Spring Containers가 제공하는 핵심 기술로서 IOC는 종속성의 활성 관리에서 Spring 컨테이너에 의한 종속성의 글로벌 제어에 이르기까지 종속성의 역전을 성공적으로 완료했습니다.
이 작업의 이점은 무엇입니까?
물론, 그것은 소위 "분리"로, 프로그램 모듈 간의 관계를보다 독립적으로 만들 수 있습니다. Spring은 이러한 모듈 간의 종속성을 제어하고 컨테이너 시작 및 초기화 프로세스 중에 이러한 종속성을 기반으로 이러한 모듈을 작성, 관리 및 유지해야합니다. 모듈 간의 종속성을 변경 해야하는 경우 프로그램 코드를 변경할 필요조차 없습니다. 변경된 종속성 만 수정하면됩니다. Spring은 컨테이너를 다시 시작하고 초기화하는 과정에서 이러한 새로운 종속성을 다시 설정합니다. 이 프로세스에서 코드 자체가 모듈의 특정 종속성 상황 선언을 반영 할 필요는 없지만 필요한 모듈의 인터페이스 만 정의하면됩니다. 따라서 이것은 일반적인 인터페이스 지향 아이디어입니다. 동시에, 구성 파일 또는 주석 형태로 종속성을 표현하는 것이 가장 좋습니다. 관련 스프링 처리 클래스는 이러한 외부 구성 파일을 기반으로 모듈을 조립하거나 주석을 스캔하여 내부 주석 프로세서를 호출하여 모듈을 조립하여 IOC 프로세스를 완료합니다.
IOC의 목적은 DI라는 의존성 주입입니다. IOC 기술을 통해 Ultimate Container는 모듈 간의 종속성 주입을 완료하는 데 도움이됩니다.
또한 마지막 요점은 Spring IOC 과정에서 항상 위의 메인 라인에 대해 명확해야한다는 것입니다. 실시간 구문과 클래스 구조가 아무리 복잡하더라도, 기능과 목적은 설명 된 구성 파일에 "도면"으로 의존하여 모듈의 "어셈블리"를 완성하는 것입니다. 복잡한 구문은이 목적을 달성하기위한 수단 일뿐입니다.
소위 IOC 프로토 타입은 가장 간단한 IOC 회로도를 보여주기 위해이 프로세스를 설명하기 위해 완전히 간단한 프로토 타입을 만들 수도 있습니다.
먼저, 기본 모듈과 두 인터페이스로 정의 된 종속성 모듈을 포함하여 여러 가지 모듈이 있습니다.
클래스 MainModule {private fectionModulea modulea; 개인 의존 모드 룰브 모듈; public dependmodulea getModulea () {return modulea; } public void setModulea (fectionModulea modulea) {this.modulea = modulea; } public deppendModuleB getModuleB () {return moduleb; } public void setModuleb (fextmoduleb moduleb) {this.moduleb = moduleb; }} interface fextModulea {public void funcfrommodulea ();} 인터페이스 의존 moduleb {public void funcfrommoduleb ();} class fextModuleaimpl emplics expendModUlea {@OverRide public void funcfrommodeUea () {System.out.println ( "이것은 MOD A a"); }} class fextModuleBimpl은 fextModuleB {@override public void funcffommoduleb () {System.out.println ( "모듈 b에서 func"); }}IOC를 채택하지 않지만 주 모듈 자체에 의존하여 종속 모듈의 생성을 제어하면 다음과 같습니다.
public class simpleiocdemo {public static void main (String [] args)은 classNotFoundException {mainModule mainModule = new MainModule (); mainModule.setModulea (new fexplemoduleAimpl ()); mainModule.setModuleB (new feptionModuleBimpl ()); mainModule.getModulea (). funcfrommodulea (); mainModule.getModuleb (). funcfrommoduleb (); }}이것은 IOC 컨테이너 프로토 타입의 단순화 된 정의입니다. 시작 후 컨테이너가 초기화되면 사용자가 작성한 구성 파일을 읽습니다. 여기서는 간단한 속성 구성 파일을 예로 들어 보겠습니다. 사용자가 GetBean 메소드를 호출 할 때만 해당 Bean은 구성 파일에 따라 진정으로 조립 및로드됩니다. 조립 된 Bean을 저장하는 데 사용되는 맵은 우리가 정의한 컨테이너 프로토 타입 내부에 유지됩니다. 요구 사항을 충족하는 콩이있는 경우 다시 만들 필요가 없습니다.
클래스 Simpleioccontainer {private properties properties = new Properties (); 개인지도 <문자열, 개체> modulemap = new Hashmap <> (); {try {properties.load (new FileInputStream (새 파일 ( "simpleioc.properties"))); } catch (예외 e) {e.printstacktrace (); }} public Object getBean (String modulename)은 classNotFoundException {Object InstanceObj; if (modulemap.get (modulename)! = null) {System.out.println ( "return Old Bean"); return modulemap.get (modulename); } system.out.println ( "새 bean 만들기"); 문자열 fullClassName = properties.getProperty (modulename); if (fullClassName == null) 새 classNotFoundException ()을 던지십시오. else {class <? 객체를 확장합니다> clazz = class.forname (fullclassName); try {instanceobj = clazz.newinstance (); instanceObj = buildAtachedModules (modulEname, instanceObj); modulemap.put (moduleName, instanceObj); return instanceobj; } catch (InstantiationException e) {e.printstacktrace (); } catch (delegalAccessException e) {e.printstacktrace (); }} return null; } private object buildAttachedModules (String moduleName, 객체 인스턴스 OBJ) {set <string> propertiesKeys = properties.StringPropertyNames (); 필드 [] fields = instanceObj.getClass (). getDeclaredFields (); for (string key : propertieskeys) {if (key.contains (modulename) &&! key.equals (modulename)) {try {class <? 객체를 확장> clazz = class.forname (properties.getProperty (properties.getProperty (key))); for (field field : fields) {if (field.gettype (). isassignablefrom (clazz)) field.set (instanceobj, clazz.newinstance ()); }} catch (예외 e) {e.printstacktrace (); }}} return instanceObj; }}이것은 속성 구성 파일을 사용하여 쓴 종속성 구성 파일입니다. 이 구성 파일은 어셈블리 모듈의 "도면"입니다. 여기의 구문은 우리에 의해 완전히 정의됩니다. 실제 스프링 IOC 컨테이너에서보다 복잡한 종속성 로직을 표현하기 위해보다 개발 된 XML 형식 구성 파일 또는 최신 주석 구성이 사용되며 주석 프로세서가 드로잉 분석을 완료하는 데 사용됩니다.
MainModule = com.rocking.demo.mainModuleMainModule.Modulea = moduleamainModule.ModuleB = ModuleBModulea = com.Rocking.demo.DependModuleAimplModuleB = com.rocking.demo.depectulebimpl
이것이 테스트 코드입니다. 정의한 IOC 컨테이너를 통해 요구 사항을 충족하는 모듈을 완전히 얻을 수 있음을 알 수 있습니다. 동시에, 우리는 우리가 정의한 용기가 우리를 위해이 콩을 유지할 수 있음을 알 수 있습니다. 콩이 조립되고 만들어지면 다시 만들 필요가 없습니다.
public class simpleiocdemo {public static void main (String [] args)은 classNotFoundException {simpleioccontainer container = new Simpleioccontainer (); fextmodulea modulea = (fectionModulea) container.getBean ( "modulea"); modulea.funcfrommodulea (); fextModuleb moduleb = (fextmoduleb) container.getBean ( "moduleb"); moduleb.funcfrommoduleb (); mainModule mainModule = (mainModule) container.getBean ( "mainModule"); mainModule.getModulea (). funcfrommodulea (); mainModule.getModuleb (). funcfrommoduleb (); container.getBean ( "mainModule"); }}이것은 IOC의 기본 아이디어를 기반으로 만든 IOC 컨테이너 프로토 타입입니다. Spring IOC는 복잡한 구문을 가지고 있지만 결국 완료된 작업은 핵심에서 동일하며 소위 "모든 변경 사항은 본질과 분리되지 않습니다".
스프링 IOC 특정 프로세스
지난번에 IOC의 일반적인 구현 프로토 타입이 보여졌습니다. 그렇다면 메타 데이터 메타 정보 구성을 기반 으로이 컨테이너의 스프링 프레임 워크에서 POJO를로드하는 프로세스를 구체적으로 구현하는 방법은 무엇입니까? 전체 Spring IOC 컨테이너 작업 프로세스에는 상당히 유연하게 설계된 곳이 많이 있으며, 컨테이너의 기계적 프로세스를 완료하지 않고 사용자에게 자체 작업을 완료 할 수있는 많은 공간을 제공합니다.
이것은 전체 IOC 컨테이너 작업 프로세스의 프로세스 다이어그램입니다.
1. 컨테이너 시작 단계 (1) 구성 파일 정보로드 (2) 구성 파일 정보 분석 (3) 어셈블리 BeanDefinition
(4) 후 처리 후 먼저 구성 파일 또는 주석 및 Javabean 클래스 정보와 같은 메타 정보가 IOC 컨테이너에로드됩니다. 컨테이너는 XML- 형식 구성 파일을 읽습니다. 이 구성 파일은 사용자와 특별한주의가 필요한 어셈블리가 선언 한 종속성입니다. 콩을 조립하기위한 초기 "외부 도면"입니다. 컨테이너의 구문 분석 엔진은 컨테이너 내부에서 인식 할 수있는 콩화 형식으로 쓸 텍스트 형식의 문자 메타 정보를 구문 분석 할 수 있으며, 이는 콩화를 이해할 수 있습니다. 반사 메커니즘과 유사한 클래스 구조가됩니다. Javabeans 및 Configuration 파일을 분석하여 얻은이 Beandefinition은 요구 사항을 충족하는 Javabean을 조립하는 기본 구조를 얻습니다. Beandefinition 외에도 Beandefinition을 수정 해야하는 경우이 후 처리가 수행됩니다. 사후 처리는 일반적으로 스프링 프레임 워크에서 BeanFactoryPostossor를 통해 처리됩니다.
우리는 여전히 우리가 지난번에 사용한 예제를 사용 하여이 beandefinition의 작동 원리를 설명합니다. 주 콩, 기본 모듈 mainmodule 및 종속성 모듈의 종속 모듈 및 종속 모듈이 있습니다. 전자는 후자의 두 모듈에 의존합니다. 구성 파일에서 일반적으로 다음과 같은 종속성을 선언합니다.
<? xml 버전 = "1.0"alcoding = "utf-8"?> <beans xmlns = "http://www.springframework.org/schema/beans"xmlns : xsi = "http://ww.w.w3.org/2001/xmlschema-instance" xsi : schemalocation = "http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"> <bean id = "mainModule"> 이름 = "moduleb"> <Ref bean = "moduleb"/> </property> </bean> <bean id = "modulea"> </bean> <bean id = "moduleb"> </bean> </beans>
이것은 위의 구성 파일에 대한 표준 BeanFactory 컨테이너 (Spring IOC 컨테이너의 구현 중 하나)의 어셈블리를 보여주는 프로그램입니다.
클래스 MainModule {private fectionModulea modulea; 개인 의존 모드 룰브 모듈; public dependmodulea getModulea () {return modulea; } public void setModulea (fectionModulea modulea) {this.modulea = modulea; } public deppendModuleB getModuleB () {return moduleb; } public void setModuleb (fextmoduleb moduleb) {this.moduleb = moduleb; }} interface fextModulea {public void funcfrommodulea ();} 인터페이스 의존 moduleb {public void funcfrommoduleb ();} class fextModuleaimpl emplics expendModUlea {@OverRide public void funcfrommodeUea () {System.out.println ( "이것은 MOD A a"); }} class fextModuleBimpl은 fextModuleB {@override public void funcffommoduleb () {System.out.println ( "모듈 b에서 func"); }} public class simpleiocdemo {public static void main (string [] args)은 classNotFoundException {defaultListableBeanFactory BeanFactory = new DefaultListableBeanFactory (); XMLBEANDEFINITIONREADER Reader = New XMLBeanDefinitionReader (BeanFactory); reader.loadBeanDefinitions ( "beans.xml"); mainModule mainModule = (mainModule) beanFactory.getBean ( "mainModule"); mainModule.getModulea (). funcfrommodulea (); mainModule.getModuleb (). funcfrommoduleb (); }}여기서 우리의 구성 파일과 Javabean은로드 및 읽기 및 구문 분석됩니다. 여기서 Beandefinition 생성 및 사용 프로세스가 숨겨져 있습니다. 이것은 실제로 IOC 내부에서 발생하는 일반적인 프로세스입니다.
public class simpleiocdemo {public static void main (string [] args)은 classNotFoundException {defaultListableBeanFactory BeanFactory = new DefaultListableBeanFactory (); AbstractBeanDefinition MainModule = New RootBeanDefinition (MainModule.class); AbstractBeendefinition modulea = 새로운 rootbeandefinition (fextmoduleaimpl.class); AbstractBeanDefinition ModuleB = New RootBeanDefinition (fextModuleBimpl.class); beanfactory.registerbeanDefinition ( "mainModule", mainModule); beanfactory.registerbeandefinition ( "modulea", modulea); beanfactory.registerbeandefinition ( "moduleb", moduleb); MutablePropertyValues propertyValues = new MutablePropertyValues (); PropertyValues.add ( "modulea", modulea); PropertyValues.add ( "moduleb", moduleb); MainModule.SetPropertyValues (PropertyValues); mainModule module = (mainModule) beanFactory.getBean ( "mainModule"); module.getModulea (). funcfrommodulea (); module.getModuleb (). funcfrommoduleb (); }}XML의 메타 정보를로드 및 읽은 후 IOC 구문 분석 엔진은 실제 유형을 기반으로 언급 된 모듈을 Beandefinition으로 만듭니다. 이 beandefinition은 반사 또는 프록시 프로세스로 간주 될 수 있습니다. 목적은 IOC 컨테이너를 향후 생성 할 인스턴스 객체의 Bean 구조를 지우는 다음 이러한 Bean 구조를 BeanFactory에 등록한 다음 기본 모듈의 종속성을 세터 주입 형태로 기본 모듈의 특성에 추가하는 것입니다 (이는 모든 콩의 정의에 따라 세트 모듈에 의해 제공된 세터 방법 또는 메인 모듈에 의해 제공되는 초기화 방법에 의존합니다.). 그런 다음 GetBean 방법에 전화하여 요구 사항을 충족하는 콩을 생산하십시오. 이것은 프로세스의 다음 단계이며 나중에 그것에 대해 이야기 할 것입니다.
BeanDefinition의 "도면"에 대한 정보를 BeanFactory에 등록한 후에도 등록 된 BeanDefinition을 변경할 수 있습니다. 이것은 앞에서 언급 한 사용자를위한 스프링 디자인의 유연한 측면 중 하나입니다. 그것은 모든 프로세스가 통제 할 수 없다는 것을 의미하지는 않지만 사용자가 많은 곳에서 플레이 할 수있는 많은 공간을 남깁니다. 구체적인 방법은 BeanFactory 프로세서 BeanFactoryPostprocessor를 사용하여 BeanFactory 처리에 개입하여 수정 해야하는 BeanDefinition 부분을 추가로 작성하는 것입니다. 이 프로세스는 프로세스의 "사후 처리"프로세스에 해당합니다.
공통 프로세서 중 하나를 사용하여 속성 자리 표시 자 구성 프로세서를 예로 들어, 해당 BeanDefinition 속성의 내용이 구성 프로세서 지정된 구성 파일의 정보로 수정되도록 등록 된 BeanFactory를 구축 한 후에 등록 된 BeanFactory를 처리하는 것입니다.
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(beanFactory);reader.loadBeanDefinitions( new ClassPathResource( "Beans.xml"));PropertyPlaceholderConfigurer configurer = new PropertyPlaceholderConfigurer();configurer.setLocation( New ClassPathResource ( "about.properties")); configurer.postProcessBeanFactory (beanfactory);
BeanFactoryPostProcessor는 BeanFactory를 처리합니다. 결과적으로 BeanDefinition에 정의 된 일부 속성을 BeanFactoryPostProcessor의 위치에있는 일부 정보로 변경하는 것입니다.
2. Bean Instantiation Stage
Beandefinition의 처리 된 "내부 도면"의 지침에 따라 컨테이너는 반사 또는 CGLIB 동적 바이트 코드 생성을 통해 메모리에 존재하는 활성화 된 인스턴스 객체로 더 전환 한 다음, BeanDefinition에 의해 지정된 Setter Incection Instrection 또는 초기화 주입을 통해 BeanDefinition에 의해 지정된 종속성 객체를 조립할 수 있습니다. 여기서, 종속성 객체의 참조는 실제로 의존 해야하는 객체 속성에 할당된다.
그러나 여기서 생성 된 인스턴스는 단순한 Bean 정의의 간단한 인스턴스 일뿐 만 아니라 스프링으로 래핑 한 콩 전환 인스턴스라는 점에 유의해야합니다. 왜 콩 전원 방법으로 콩을 감싸는 데 사용해야합니까? BeanWrapper는 Bean 특성에 균일하게 액세스하는 인터페이스를 제공하기 때문입니다. 기본 Bean 프레임 워크를 작성한 후 속성을 설정해야합니다. 각 콩의 세터 방법은 다르므로 반사로 직접 설정하면 매우 복잡합니다. 따라서 Spring 은이 래퍼를 제공하여 속성 설정을 단순화합니다.
beanwrapper beanwrapper = new beanwrapperimpl (class.forname ( "com.rocking.demo.mainmodule"); beanwrapper.setpropertyvalue ( "modulea", class.forname ( "com.rocking.demo.depmoduleAimpl"); newWrapper.setProperValue ( ") class.forname ( "com.rocking.demo.depmodulebimpl"). newInstance ()); mainModule mainModule = (mainModule) beanWrapper.getWrapedInstance (); mainModule.getModulea (). funcfroma (); mainModule.getModuleB ();
위의 과정은 봄에 클래스의 반사 용기를 얻고 포장을 만들어 향후 포장 된 인스턴스 Bean의 구조를 이해할 수 있음을 보여줍니다. Unified 속성 설정 방법 SetPropertyValue를 사용 하여이 패키지의 인스턴스에 대한 속성을 설정하십시오. 얻은 최종 Bean 인스턴스는 getwrappedInstance를 통해 얻어지며 그 속성이 성공적으로 할당되었음을 알 수 있습니다.
현재 Bean 인스턴스는 실제로 완전히 사용 가능하지만 Spring은 인스턴스화 단계 에서이 단계에서 사용자의 개입을 완료하기 위해 유연한 전략을 준비했습니다. 컨테이너 시작 단계에서 BeanFactoryProcessor Control BeanDefinition과 유사하게, 인스턴스화 단계에서 Spring은 조립 된 인스턴스에서 작동 할 수있는 BeanPostProcessor 프로세서를 제공하여 가능한 변경 사항을 완료합니다.
다음은 BeanPostProcessor 구현 클래스를 정의하고 PostprocessAfterinitialization 및 postprocessbeforeinitialization을 구현하여 Bean 인스턴스 어셈블리 후에 개별적으로 수행되는 작업을 정의하는 방법을 설명하는 예입니다. BeanFactory 가이 프로세서를 추가 한 후, GetBean 메소드가 조립 될 때마다 "도면"(어셈블리 프로세스 중에 생성 된 종속 인스턴스 Bean 포함)에 따라 Bean 인스턴스에서 두 가지 메소드가 호출됩니다. 이 방법은 이러한 Bean 인스턴스를 수정할 수 있습니다.
다음은 다음과 같은 예입니다 (MainModule 및 그 종속성은 이전 에이 기사의 이전과 동일합니다).
클래스 모듈레 크 {개인 문자열 x; 공개 문자열 getx () {return x; } public void setx (문자열 x) {this.x = x; }} 클래스 modulepostprocessor는 beanpostprocessor를 구현합니다. {@override public Object postProcessAfterinitialization (Object Object, String String)은 beansexception {system.out.println (String); if (객체 인스턴스의 modulec) {system.out.println (문자열); ((modulec) 객체) .setx ( "After"); } 반환 객체; } @override public Object PostProcessbeforeInitialization (Object Object, String String)은 BeanSexception {if (개체 인스턴스 모듈 렉) {((modulec) object) .SETX ( "provery"); } 반환 객체; }} public class vertysimpleiockernal {public static void main (string [] args)은 classNotFoundException, BeanSexception, InstantiationException, 불법적 인 BeanFactory BeanFactory = 새로운 DefaultListableBeanCactory (); XMLBEANDEFINITIONREADER Reader = New XMLBeanDefinitionReader (BeanFactory); reader.loadBeanDefinitions (New ClassPathResource ( "beans.xml")); ModulePostProcessor postprocessor = new ModulepostProcessor (); beanfactory.addbeanpostprocessor (postprocessor); mainModule module = (mainModule) beanFactory.getBean ( "mainModule"); Modulec Modulec = (modulec) beanfactory.getBean ( "modulec"); System.out.println (modulec.getx ()); }}Bean의 종속성 구성 파일입니다.
<? xml 버전 = "1.0"alcoding = "utf-8"?> <beans xmlns = "http://www.springframework.org/schema/beans"xmlns : xsi = "http://ww.w.w3.org/2001/xmlschema-instance" xsi : schemalocation = "http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> id id "> id"id "id"id "id 이름 = "modulea"> <ref bean = "modulea"/> </property> <속성 이름 = "moduleb"> <Ref bean = "moduleb"/</property> </bean> <bean id = "modulea"> <property name = "infoa"> <value> $ {modulea.infoa} </value> </bean> <id = "id ="id = "id ="id = " <value> 모듈의 정보 </value> </property> </bean> <bean id = "modulec"> </bean> </beans>최종 결과에서 GetBean 메소드를 호출하여 얻은 GetBean 인스턴스 (종속성에 의해 생성)가 Pre- 프로세스 및 사후 처리를 위해 BeanPostProcessor에 의해 검색 될 때마다 알 수 있습니다.
위의 BeanPostProcessor와 유사한 조립 된 Bean을 처리하는 것 외에도 Spring은 Init-Method 및 Destroy 방법을 구성하여 Bean의 초기화 및 파괴 프로세스를위한 콜백 기능을 설정할 수도 있습니다. 이러한 콜백 기능은 또한 Bean 인스턴스를 변경할 수있는 기회를 유연하게 제공 할 수 있습니다.
전체 스프링 IOC 프로세스는 실제로 IOC 프로세스가 사용자에게보다 유연하고 효과적으로 공간을 제공 할 수 있다는 점을 제외하고는 실제로 우리가 쓴 IOC 프로토 타입과 본질적으로 동일합니다. 또한 Spring의 IOC는 보안, 컨테이너 안정성 및 메타 데이터에 대한 정교한 디자인을 Bean 변환 효율로하여 IOC의 기초를 스프링 컨테이너로 만들었습니다.