Light
weight containers were born when people frown at the intrusion
mandated by heavy weight solutions such as EJB.Небольшой вес
контейнеров родились, когда люди недовольны вторжением в
соответствии с тяжелым весом, таких как EJB. We
like to write pojo's; we don't want to implement any funny
interfaces or super classes.Мы очень любим писать в pojo; Мы
не хотим осуществлять любые смешные супер интерфейсов или классов.
Yet,
it is a pity if a container still mandates certain programming
styles.Но совсем обидно, если контейнер еще мандаты некоторых
стилях программирования.
Some people may prefer
setter injection which is good at optional dependencies; Some may
prefer constructor injection that precludes interim stale state of
objects; Some people like me would like to be able to create object
using static factory; when all these are allowed, we may start
asking for the ability to combine them.Некоторые люди
предпочитают инъекции задавала который ни на факультативной
зависимостей; Некоторые могут предпочесть строителя впрыска, что
исключает промежуточные застойное состояние объектов; Некоторые
люди, как мне хотелось бы иметь возможность создавать объект с
помощью статической фабрика; когда все это разрешено, мы можем
начать просьбой о возможности их объединения. blah
blah blah.и так и так и так.
None
of these are universally superior to the others.Ни одна из
них над всеми другими. That's why an open
container better not simply say no to any of these injection
methods.Вот почему открытый контейнер, лучше не просто
говорить "нет" на любой из этих методов инъекций. In
the Injection
Methods Compared section, we did a comparison of the injection
methods supported by these containers.В сравнении
Методы Инъекции разделе мы делали сравнение методов инъекций при
поддержке этих контейнеров.
Dependency Injection for
objects not created by containerЗависимость от инъекций на
объекты не создавались в контейнере
Other
than injection methods, there may still be other assumptions that
could become restrictions.Другие методы, чем впрыск, все еще
могут быть другие предположения, которые могли бы стать ограничения.
For
example: all components are managed by the container.Например
: все компоненты управляет контейнер.
Or:
only instances created by the container need dependency
injection.Или : только в случаях, созданных в контейнере
need-зависимость инъекций.
Once
this assumption is made, the container is not so open because it
refuses to manage dependencies for objects not created by the
container.Как только это предположение делается, контейнер не
так открыто потому, что он отказывается управлять зависимостей для
объектов, созданных не в контейнере.
As an
example, let's think about domain objects constructed by a
persistence framework such as Hibernate.Как пример, давайте
подумаем о доменных объектов, построенных сохранением структуры,
такой как Hibernate. It is very possible that
the persistence framework has no knowledge of the container (and
should not) and simply created these instances by calling the
constructor.Вполне возможно, что сохранение рамок не знает,
баллон (и не должен), а просто создали эти случаи по телефону
конструктора.
Nonetheless, there may
still be dependencies that need to be injected if these domain
objects are rich domain objects as described hereТем не менее,
все еще могут быть зависимостями, которые должны быть нагнетаемой,
если эти объекты домена домен богаты объектами, как описано здесь
..
A
naive solution may just obtain a reference to the container and set
the dependencies manually:Наивно раствор может просто
получить ссылку на контейнер и набор зависимостей вручную :
pubic class BankService{ public BankAccount getBankAccount(...){ BankAccount acct = (BankAccount)session.getById(...); Bank bank = (Bank)session.getById(...); acct.setProperty1((ABC)container.getInst ance( "abc" )); acct.setProperty2((DEF)container .get Insance( "def" )); bank.setProperty1((XYZ)container.getInst ance( "xyz" )); acct.setBank(bank); return acct; }BankService лобковых класс BankAccount (общественных getBankAccount (...){ BankAccount = acct- (BankAccount) session.getById банка ... банка = (банка) session.getById ... acct.setProperty1((ABC)container.getInst ние ( "abc" ));
acct.setProperty2((DEF)container .get Insance ( "польскую нотацию")); bank.setProperty1((XYZ)container.getInst ние ( "xyz")); acct.setBank (банка); вернуться acct-;)
Works, but not scalable and
not configurable.Работает, но не масштабируемой и не
настраивается.
It is
natural to feel bad about having to do this since we already have a
dependency injection framework - the container, why do we still have
to do injection in a different place manually?Вполне
естественно чувствовать себя плохо тем, что им приходится это
делать, поскольку у нас уже есть зависимость от инъекций основа -
контейнер, Почему же нам еще делать инъекции в разные места вручную?
Plus,
this solution effectively locks you in with whatever the container
framework you use.Плюс, такое решение эффективно блокирует
вас в любую контейнер базы вы используете. An
unnecessary dependency on the container is
introduced.Зависимость от ненужной контейнер представляет.
The
worst thing about this solution, IMHO, is that the Java code and the
container have to agree on all these "abc", "def", "xyz"
names.Хуже всего это раствор, по моему, заключается в том,
что Java код, и контейнер приходится соглашаться на все эти "abc",
"польскую нотацию", "xyz" имена. That
clutters up the global namespace of the container and mandates too
strong a coupling between the Java code and the container.Это
clutters до глобальных имен в контейнер и мандаты слишком сильным
взаимодействие между Java и код контейнера.
SolutionРаствор
Spring gives a solution for
this senarios using the "AbstractAutowireCapableBeanFactory.appl
yBeanPropertyValues()" method.Весна дает решение для этой
senarios использовании "AbstractAutowireCapableBeanFactory.appl
yBeanPropertyValues()" метод. It is better than not
having it, but this solution also locks you into the Spring
framework.Это лучше, чем не имеющие его, но это решение также
блокирует вас в рамках Весна. The Java code has to
introduce dependency on Spring's API, which doesn't 100% follow the
Dependency Injection phylosophy.Java код ввести зависимость
от Весна в API, что не 100% последующая зависимость Инъекции LAN.
Ideally, our business
objects should be able to just wait for everything they need to be
"push"ed to them, rather than going out "pull"ing them using various
API's such as "applyBeanPropertyValue".В идеале наш бизнес
объекты должны быть в состоянии только ждать, пока все они должны
быть "толчок", способствуют их а не выходить на улицу "вывести" их
интересы с помощью различных API, такими, как
"applyBeanPropertyValue".
The
following describes a solution in Nuts.Ниже рассматривается
решение в орехах.
First, let's forget about
container crap and abstract the problem we face.Во-первых,
давайте забывать о контейнер дерьма и абстрактных проблем, с
которыми мы сталкиваемся. Since we want to
externalize the "dependency injection" for the BankAccount object,
we need an interface that models this concept:Поскольку мы
хотим, чтобы иностранные "зависимость от инъекций" для BankAccount
объект, нам нужно чтобы интерфейс моделей данной концепции :
public interface BankAccountInjector{ void inject(Bank bank, BankAccount acct); }публичный интерфейс BankAccountInjector (вдохнуть вакуум (банк банк acct- BankAccount);)
We
include both Bank and BankAccount as parameters because these two
are inter-coupled in the dependency injection.Мы включаем оба
берега и BankAccount как параметры, поскольку эти два понятия - в
сочетании в зависимости инъекций. With
this interface, the code becomes:При этом интерфейс, код
становится :
pubic class BankService{ private final BankAccountInjector injector; public BankAccountService(BankAccountInjector injector){ this .injector = injector; } public BankAccount getBankAccount(...){ BankAccount acct = (BankAccount)session.getById(...); Bank bank = (Bank)session.getById(...); injector.inject(bank, acct); return acct; } }лобковой класс BankService (личном BankAccountInjector инжектор; государственных BankAccountService (BankAccountInjector инжектор) (это. = инжектор инжектор;) государственного BankAccount getBankAccount (...){ BankAccount = acct- (BankAccount) session.getById банка ... банка = (банка) session.getById ... injector.inject (банк, acct-); Вернуться acct-;))
The
code now is cleaner.Теперь код чище. All
dependency injection logic are encapsulated in the
BankAccountInjector interface.Все инъекции зависимость
логики, инкапсулированы в BankAccountInjector интерфейс.
The
only problem left is how we can inject the BankAccountInjector
object into BankService.Единственная проблема заключается в
том, как покинули мы можем вдохнуть в объект BankAccountInjector
BankService. And that can be done in
Nuts.И что можно сделать в скорлупе.
First, we will use the
<function> tag to spell out the whole injection
logic:Во-первых, мы будем использовать тег <function>
расшифровывать весь впрыск логики :
<function id= "injection" params= "bank, acct" > <sequence> <bean component= "$bank" > <prop key= "xyz" > <ctor class= "XYZ" .../> </prop> </bean> <bean component= "$acct" > <prop key= "abc" > <ctor class= "ABC" .../> </prop> <prop key= "def" > <ctor class= "DEF" .../> </prop> <prop key= "bank" val= "$bank" /> </bean> </sequence> </function><function id= "injection" params= "bank, acct"> <sequence> <bean component= "$bank"> <prop key= "xyz"> <разрушен класс = "XYZ" .../> </prop> </bean> <bean component= "$acct"> <prop key= "abc"> <ctor class= "ABC" .../> </prop> <prop key= "def"> <ctor class= "DEF" .../> </prop> <= Предл ключ "банковские" арс = "$ банке" /> </bean> </sequence> </function>
This
function takes bank and bank account as two parameters.Эта
функция принимает банковские и банковскими счетами, как два
параметра. It then uses a
<sequence> tag to sequentially execute two steps to set
dependencies for bank and bank account.Затем она использует
тег для <sequence> последовательно выполнить два шага
определить зависимости для банка и банковского счета.
Once
we have the function defined, we can use the <factory> tag to
adapt a function to the BankAccountInjector interface:Когда
мы принимаем определенные функции, мы можем использовать тег
<factory> адаптировать функцию BankAccountInjector интерфейса
:
<factory id= "injector" type= "BankAccountInjector" component= "$injection" /><factory id= "injector" type= "BankAccountInjector" component= "$injection" />
The
<factory> tag internally creates a dynamic proxy that
implements this interface and uses the function as the
implementation.<factory> Тег создает внутри
динамических прокси, которые реализует этот интерфейс и
используется, как функция реализации.
When
wiring up the BankService component, we can say:При монтаже
до BankService компонент, мы можем сказать :
<ctor id= "bankservice" class= "BankService" args= "$injector" /><ctor id= "bankservice" class= "BankService" args= "$injector" />
Therefore, even for objects
not created by Nuts, Nuts can still inject dependency for it without
any intrusion to the business object design.Поэтому, даже для
объектов, созданных не в скорлупе, Орехи можно еще добавлять
зависимость для него без какого-либо вмешательства в бизнес объект
дизайна.
We
believe this feature is unique and makes Nuts an extremely open
container.Мы считаем, что эта особенность является уникальной
и делает орехи очень открытый контейнер.