Весна IOC -прототип
Основной ядро и отправная точка структуры пружины, несомненно, IOC. В качестве основной технологии, предоставленной весенними контейнерами, МОК успешно завершила инверсию зависимостей: от активного управления основным классом от зависимостей к глобальному контролю зависимостей с помощью пружинных контейнеров.
Каковы преимущества этого?
Конечно, это так называемое «развязка», которая может сделать взаимосвязь между модулями программы более независимой. Пружина должна контролировать зависимости между этими модулями и создавать, управлять и поддерживать эти модули на основе этих зависимостей во время запуска контейнера и процесса инициализации. Если вам нужно изменить зависимости между модулями, вам даже не нужно изменять код программы. Вам нужно только изменить измененные зависимости. Spring будет восстановить эти новые зависимости в процессе запуска и инициализации контейнера снова. В этом процессе необходимо отметить, что сам код не должен отражать объявление о конкретной ситуации зависимости модуля, но только необходимо определить интерфейс требуемого модуля. Следовательно, это типичная идея, ориентированная на интерфейс. В то же время лучше всего выразить зависимости в форме файлов конфигурации или аннотаций. Соответствующие классы обработки пружины будут собирать модули на основе этих внешних файлов конфигурации или сканировать аннотацию, чтобы вызвать процессор внутреннего аннотации для сборки модулей для завершения процесса МОК.
Целью МОК является инъекция зависимости, называемая DI. Благодаря технологии МОК, конечный контейнер поможет нам завершить инъекцию зависимости между модулями.
Кроме того, последняя точка состоит в том, что в процессе пружины МОК мы всегда должны быть ясны по поводу вышеуказанной основной линии. Независимо от того, насколько сложны синтаксис и структура класса в реальном времени, его функция и цель одинаковы: он должен завершить «сборку» модуля, полагаясь на описанный файл конфигурации как сборка «чертежа». Сложный синтаксис - это просто средство для достижения этой цели.
Так называемый прототип МОК, чтобы показать самую простую схему МОК схематической схемы, мы могли бы также сделать совершенно простой прототип, чтобы проиллюстрировать этот процесс:
Во -первых, мы определяем несколько модулей, включая основной модуль и модуль зависимости, определяемый двумя интерфейсами:
класс MainModule {private DevingDomodulea modulea; Private DevendModuleb ModuleB; Public DevendModulea getModulea () {return Modulea; } public void setModulea (DevingModulea modulea) {this.modulea = modulea; } public Devidenmoduleb getModuleb () {return moduleb; } public void setModuleb (devendModuleb moduleb) {this.moduleb = moduleb; }} интерфейс Devidenmodulea {public void funcfromDulaue ();} интерфейс DeviewModuleb {public void funcfromDuleb ();} класс DeviewModuleaImpl реализует DeviewModulea {@Override public void funcfromdulea () {System.out.println (»(это Func от module a»); }} класс DevingDomoduleBimpl реализует DevingModuleb {@Override public void funcfromDuleb () {System.out.println ("Это функция из модуля B"); }}Если мы не примем МОК, но полагаемся на сам основной модуль для управления созданием его зависимого модуля, то это будет похоже на это:
public class simpleiocdemo {public static void main (string [] args) бросает classnotfoundexception {mainmodule mainmodule = new mainmodule (); mainmodule.setmodulea (new DevingDomoduleaimpl ()); mainmodule.setmoduleb (new DevingDomoduleBimpl ()); mainmodule.getmodulea (). funcfromdulea (); mainmodule.getmoduleb (). funcfromduleb (); }}Это наше упрощенное определение прототипа контейнера МОК. Когда контейнер инициализируется после запуска, он будет считывать файл конфигурации, записанный пользователем. Здесь мы принимаем простой файл конфигурации свойств в качестве примера. Только когда пользователь вызывает метод GetBean, соответствующий фасоль будет по -настоящему собран и загружен в соответствии с файлом конфигурации. Карта, используемая для сохранения собранного фасоли, поддерживается внутри прототипа контейнера, который мы определили. Если есть боб, который соответствует требованиям, его не нужно снова создавать:
Class SimpleiocContainer {Private Properties Properties = new Properties (); Приватная карта <string, object> modulemap = new hashmap <> (); {try {properties.load (new FileInputStream (new File ("simpleioc.properties"))); } catch (Exception e) {e.printstackTrace (); }} public Object getBean (String Modulename) Throws classnotFoundException {ocyation ancessObj; if (modulemap.get (modulename)! = null) {System.out.println («вернуть старый бон»); return modulemap.get (modulename); } System.out.println ("Создать новый бон"); String fullClassName = Properties.getProperty (ModulEname); if (fullclassname == null) бросить новый classnotfoundexception (); else {class <? Extends Object> clazz = class.forname (fullClassName); try {ancessObj = clazz.newinStance (); exanceObj = buildattachedmodules (modulename, exanceObj); modulemap.put (modulename, exanteobj); вернуть exantsObj; } catch (instantiationException e) {e.printstacktrace (); } catch (allogalaccessexception e) {e.printstacktrace (); }} return null; } private Object BuildattachedModules (String modulename, Object ancessObj) {set <String> PropertiesS = Properties.StringPropertyNames (); Field [] fields = exanceObj.getClass (). GetDeclaredFields (); for (String Key: Propertiesseys) {if (key.contains (modulename) &&! key.equals (modulename)) {try {class <? Extends Object> clazz = class.forname (Properties.getProperty (Properties.getProperty (Key))); для (поле поле: Fields) {if (field.getType (). Isassignablefrom (clazz)) Field.set (ancemberobj, clazz.newinstance ()); }} catch (Exception e) {e.printstackTrace (); }}} return ancessObj; }}Это файл конфигурации зависимостей, который мы написали, используя файл конфигурации свойств. Этот файл конфигурации представляет собой «чертеж» нашего модуля сборки. Синтаксис здесь полностью определен нами. В контейнере IOC реальной пружины, чтобы выразить более сложную логику зависимости, более развитый файл конфигурации формата XML или более новую конфигурацию аннотации, и процессор аннотации будет использоваться для завершения анализа чертежа:
mainmodule = com.rocock.demo.mainmodulemainmodule.modulea = moduleamainmodule.moduleb = modulebmodulea = com.rocock.demo.dependmodulebmoduleb = com.rocock.demo.dependmodulebimpl
Это тестовый код. Можно видеть, что мы можем полностью получить модули, которые соответствуют требованиям через контейнер МОК, который мы определили. В то же время мы также можем обнаружить, что определенный нами контейнер может поддерживать эти бобы для нас. Когда фасоль был собран и создан, его не нужно создавать снова.
public class simpleiocdemo {public static void main (string [] args) выбрасывает classnotfoundexception {simpleioccontainer container = new Simpleioccontainer (); DEVELIDMODULEA MODULEA = (DEVELYMODULEA) Контейнер.getBean ("modulea"); modulea.funcfrommodulea (); DEVIGHTMODULEB MODULEB = (DEVELICHMODULEB) Контейнер.getBean ("ModuleB"); moduleb.funcfrommooluleb (); Mainmodule mainmodule = (mainmodule) container.getbean ("mainmodule"); mainmodule.getmodulea (). funcfromdulea (); mainmodule.getmoduleb (). funcfromduleb (); Container.getBean ("MainModule"); }}Это прототип контейнера МОК, который я создал, основанный на основной идее МОК. Хотя Spring IOC имеет сложный синтаксис, задачи, выполненные в конце, одинаковы в ядре, так называемые «все изменения не будут отделены от их сущности».
Весна специфический процесс IOC
В прошлый раз был показан прототип общей реализации МОК. Итак, как специфически реализовать процесс загрузки POJO в структуре Spring этого контейнера на основе конфигурации метаданных мета -информации? Во всем процессе контейнерных контейнеров есть много мест, которые предназначены для того, чтобы быть довольно гибкими, предоставляя пользователям много места для выполнения собственных задач, а не просто заполнение механического процесса контейнера.
Это диаграмма процесса всего рабочего процесса контейнера IOC:
1. Стадия запуска контейнера (1) Загрузка Файла конфигурации (2) Анализ информации о конфигурации (3) Ассамблея Beandefinition
(4) Сначала пост-обработка мета-информация, такая как файлы конфигурации или аннотации и информация класса Javabean, загружается в контейнер IOC. Контейнер считывает файл конфигурации XML-формата. Этот файл конфигурации является зависимостью, объявленной пользователем и сборкой, которая требует особого внимания. Это ранний «внешний рисунок» для сборки бобов. Двигатель анализа в контейнере может проанализировать мета-информацию символа в текстовой форме, которую мы пишем в боинджацию, которая может быть распознана внутри контейнера, что может понять боандж. Это становится классовой структурой, похожей на механизм отражения. Это Beandefinition, полученное путем анализа Javabeans, и файлов конфигурации получает базовую структуру сборки Javabean, которая отвечает требованиям. Если вам нужно изменить боандрирование в дополнение к Beandefinition, выполняется эта пост-обработка. Пост-обработка обычно обрабатывается через BeanFactoryPostProcessor в Spring Framework.
Мы по -прежнему используем примеры, которые мы использовали в прошлый раз, чтобы проиллюстрировать принцип эксплуатации этого Beandefinition: существует три боба, основной модуль Mainmodule и модули зависимости DevingDomodulea и DevingDuleB. Первый зависит от последних двух модулей. В файле конфигурации мы обычно объявляем такие зависимости, как это:
<? xml version = "1.0" Encoding = "UTF-8"?> <Beans xmlns = "http://www.springframework.org/schema/beans" xmlns: xsi = "http://www.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"> <pertive = "modulea-3.0 <имя свойства = "moduleb"> <ref bean = "moduleb"/> </property> </bean> <bean id = "modulea"> </bean> <bean id = "moduleb"> </bean> </beans>
Это наша программа, демонстрирующая сборку стандартного BeanFactory Container (одну из реализаций пружинных контейнеров IOC) в вышеуказанный файл конфигурации:
класс MainModule {private DevingDomodulea modulea; Private DevendModuleb ModuleB; Public DevendModulea getModulea () {return Modulea; } public void setModulea (DevingModulea modulea) {this.modulea = modulea; } public Devidenmoduleb getModuleb () {return moduleb; } public void setModuleb (devendModuleb moduleb) {this.moduleb = moduleb; }} интерфейс Devidenmodulea {public void funcfromDulaue ();} интерфейс DeviewModuleb {public void funcfromDuleb ();} класс DeviewModuleaImpl реализует DeviewModulea {@Override public void funcfromdulea () {System.out.println (»(это Func от module a»); }} класс DevingDomoduleBimpl реализует DevingModuleb {@Override public void funcfromDuleb () {System.out.println ("Это функция из модуля B"); }} public class simpleiocdemo {public static void main (string [] args) бросает classnotfoundexception {default -lectablebeanfactory beanfactory = new DefaultilebableBeanfactory (); XmlbeandefinitionReader Reader = new XmlBeanDefinitionReader (BeanFactory); reader.loadbeandefinitions ("beans.xml"); Mainmodule mainmodule = (mainmodule) beanfactory.getbean ("mainmodule"); mainmodule.getmodulea (). funcfromdulea (); mainmodule.getmoduleb (). funcfromduleb (); }}Здесь наш файл конфигурации и Javabean загружаются и прочитаны и анализируются. Здесь в нем скрыты процесс генерации и использования Beaindefinition. Это общий процесс, который на самом деле происходит внутри МОК:
public class simpleiocdemo {public static void main (string [] args) выбрасывает classnotfoundexception {default -stistablebeanfactory beanfactory = new DefaultableBeanFactory (); AbstractBeanDefinition mainModule = новый корневой рефиниции (mainmodule.class); AbstractBeanDefinition modulea = new RootBeanDefinition (DevingModuleaimpl.class); AbstractBeanDefinition moduleb = new RootBeandefinition (DevingDuleBimpl.class); beanfactory.registerbeandefinition ("mainmodule", mainmodule); beanfactory.registerbeandefinition ("Modulea", Modulea); beanfactory.registerbeandefinition ("moduleb", moduleb); MitablePropertyValues PropertyValues = new MitablePropertyValues (); PropertyValues.Add ("Modulea", Modulea); PropertyValues.Add ("ModuleB", ModuleB); mainmodule.setPropertyValues (PropertyValues); MainModule Module = (MainModule) beanFactory.getBean ("mainModule"); module.getmodulea (). funcfromdulea (); module.getmoduleb (). funcfromduleb (); }}После загрузки и считывания мета -информации XML, двигатель анализа IOC создаст модуль, упомянутый в нем в борьбу, на основе его реального типа. Это Beaindefinition можно рассматривать как отражение или прокси -процесс. Цель состоит в том, чтобы сделать контейнер IOC очистить структуру бобов объекта экземпляра, созданную в будущем, а затем зарегистрировать эти структуры бобов в BeanFactory, а затем добавить зависимости основного модуля к свойствам основного модуля в форме инъекции сеттера (это зависит от того, является ли метод установки или метод инициализации, предоставленную основным модулем), который уже зарегистрирует определение, определяемое определение Beans, указанное определение. сформировался. После этого просто позвоните в метод GetBean, чтобы произвести бобы, которые соответствуют требованиям. Это следующий этап процесса, и мы поговорим об этом позже.
После регистрации информации о «рисунке» Банддефиниции в Beanfactory мы все еще можем внести изменения в зарегистрированную боандж. Это один из гибких аспектов Spring Design для пользователей, упомянутых ранее. Это не означает, что все процессы неконтролируемые, но оставляет много возможностей для пользователей во многих местах. Конкретный метод состоит в том, чтобы использовать BeanFactory процессор BeanFactoryPostProcessor для вмешательства в обработку BeanFactory для дальнейшего переписывания части BeAndefinition, которую мы должны изменить. Этот процесс соответствует процессу «постобработки» в процессе.
Взятие одного из общих процессоров: атрибут процессора конфигурации заполнителя в качестве примера, он должен обработать зарегистрированную BeanFactory после его создания, чтобы содержимое в соответствующем атрибуте Beandefinition модифицировано для информации в указанном файле конфигурации конфигурации: Файл конфигурации: Файл конфигурации:
Default -stistablebeanfactory beanfactory = new DeflectStableBeanFactory (); XmlbeanDefinitionReader Reader = new XmlbeanDefinitionReader (beanfactory); reader.loadbeandefinitions (new classpathresource ("beans.xml"); PropertyPlaceholderConfigurer (); Configururer.SetLocation (New ClassPathresource ("about.properties")); configururer.postprocessbeanfactory (beanfactory);BeanFactoryPostProcessor будет обрабатывать BeanFactory. Результатом состоит в том, чтобы изменить некоторые атрибуты, определенные в Beaindefinition, на некоторую информацию в местоположении Beanfactorypostpostprocessor.
2. Стадия экземпляра бобов
Под руководством обработанных «внутренних рисунков» Beandefinition контейнер может дополнительно трансформировать BeAndefifnition в объект активированного экземпляра, существующий в памяти посредством отражения или динамического производства CGLIB, а затем собирать объект зависимости, указанный в BeAndefinition в новой объект экземпляра через инъекцию сеттера или инъекцию инициализации. Здесь ссылка объекта зависимости фактически присваивается атрибутам объекта, от которых необходимо зависеть.
Но здесь следует отметить, что созданный экземпляр - это не просто простой экземпляр определения бобов, а экземпляр BeanWrapper, завернутый к весне. Почему следует использовать для обертывания бобов в метод BeanWrapper? Потому что BeanWrapper предоставляет интерфейс для единого доступа к свойствам бобов. После создания основной структуры бобов необходимо установить свойства в нем. Метод сеттера каждого фасоля отличается, поэтому он будет очень сложным, если вы напрямую установите его с отражением. Следовательно, Spring предоставляет этой обертке для упрощения настройки свойства:
BeanWrapper BeanWrapper = new BeanWrapperimpl (class.forname ("com.rocking.demo.mainmodule")); Beanwrapper.setPropertyValue ("Modulea", class.forname ("com.rocockper.demo.depmoduleAimpl") "ModuleB", class.forname ("com.rocing.demo.depmodulebimpl"). newinstance ()); Mainmodule mainmodule = (mainmodule) beanwrapper.getwrappedInstance (); mainmodule.getModule (). Funcfroma (); mainmodule.getmoduleb ().Приведенный выше процесс показывает, что весной вы можете понять структуру бобов экземпляра, которая обернута в будущем, получив отражающий контейнер класса и создавая упаковку. Используйте единый метод настройки свойства SetPropertyValue, чтобы установить свойства для экземпляра этого пакета. Полученный экземпляр Bean получен через GetWrappedInstance, и вы можете обнаружить, что его атрибуты были успешно назначены.
В настоящее время экземпляр Bean на самом деле является полностью полезным, но Spring также подготовила для нас гибкие стратегии на стадии экземпляров для завершения вмешательства пользователя на этом этапе. Подобно BeanfactoryPostPostProcessor Control Beaindefinition на стадии запуска контейнера, на этапе инстанции Spring предоставляет процессор BeanpostProcessor для работы на собранные экземпляры для завершения возможных изменений:
Вот пример, чтобы проиллюстрировать, что вы определяете класс реализации BeanpostProcessor, внедряя методы послепроцессафтеринициализации и постпроцесс -рефинитизацию для определения операций, выполняемых отдельно после и до сборки экземпляра Бина. После того, как BeanFactory добавляет этот процессор, каждый раз, когда собирается метод GetBean, эти два метода будут вызывать в экземпляре боба, собранном в соответствии с «рисунком» (включая зависимый фасоль экземпляра, созданный во время процесса сборки). Эти методы могут изменить эти экземпляры бобов.
Вот пример подобного (Mainmodule и его зависимости такие же, как и ранее в этой статье):
класс modulec {private String x; public String getx () {return x; } public void setX (String x) {this.x = x; }} класс ModulePostProcessor реализует BeanpostProcessor {@Override public Object postProcessAfterinitialization (объект объекта, строка String) Throws Beansexception {System.out.println (String); if (exantec -exantef modulec) {System.out.println (String); (((Modulec) объект) .setx ("после"); } return object; } @Override public Object postProcessbeforeInitialization (объект объекта, строка строки) Throws BeanSexception {if (ExtanceOf instanceOf modulec) {((modulec) Object) .setx ("перед"); } return object; }} public class urestysimpleiockernal {public static void main (string [] args) бросает classnotfoundexception, beansexception, instantiationexception, allodalaccessexception {default -letrablebeanfactory beanfactory = new DefaultableBeanFactory (); XmlbeandefinitionReader Reader = new XmlBeanDefinitionReader (BeanFactory); reader.loadbeandefinitions (new classpathresource ("beans.xml")); Modulepostprocessor postprocessor = new ModulePostProcessor (); beanfactory.addbeanpostprocessor (постпроцессор); MainModule Module = (MainModule) beanFactory.getBean ("mainModule"); Modulec modulec = (modulec) beanfactory.getbean ("modulec"); System.out.println (modulec.getx ()); }}Это файл конфигурации зависимостей для боба:
<? xml version = "1.0" Encoding = "UTF-8"?> <Beans xmlns = "http://www.springframework.org/schema/beans" xmlns: xsi = "http://www.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"> ">" <> "<>" mainodle "> <modle yde"> ">"> ">"> ">"> ">"> ">"> ">"> ">"> ">"> ">"> ">"> ">"> ">"> ">"> "<>" <> "<>" <> ">" name = "modulea"> <ref bean = "modulea"/> </property> <property name = "moduleb"> <ref bean = "moduleb"/> </property> </bean> <bean id = "modulea"> <property name = "info"> <value> $ {modulea.infoa} </value> <//propertive> </bean> </bean> </bean> </bean> </bean> </bean> </bean> </bean> </bean> name = "Infob"> <dulch> Информация модулеба </value> </property> </bean> <bean id = "modulec"> </bean> </beans>Из конечного результата мы видим, что каждый раз, когда экземпляр GetBean (включая генерируется зависимостями), полученный по вызову метода GetBean, будет извлечен BeanpostProcessor для предварительной и постобработки.
В дополнение к обработке собранных бобов, аналогичной вышеуказанной BeanpostProcessor, Spring также может устанавливать функции обратного вызова для процесса инициализации и разрушения бобов путем настройки init-method и destry-method. Эти функции обратного вызова также могут гибко предоставить возможность изменить экземпляры бобов.
Весь пружинный процесс МОК на самом деле такой же, как и прототип МОК, который мы написали сами, за исключением того, что сложный дизайн позволяет процессу МОК предоставлять пользователям более гибко и эффективно пространство. Кроме того, Spring's IOC также достиг изысканного дизайна с точки зрения безопасности, стабильности контейнеров и эффективности преобразования бобов, делая основу IOC, контейнера для весеннего контейнера.