Что такое АОП, внедрение зависимостей и инверсия управления в простом английском - PullRequest
34 голосов
/ 03 апреля 2010

Я пытался понять концепции, связанные с AOP, Dependency Injection и Inversion of Control SPRING, но мне трудно понять это.

Кто-нибудь может объяснить это простым английским?

Ответы [ 6 ]

47 голосов
/ 04 апреля 2010

Я понимаю ваше замешательство, и мне потребовалось некоторое время, чтобы понять, как эти понятия связаны друг с другом.Вот мое (как бы личное) объяснение всего этого:

1.Инверсия управления

Инверсия управления - это довольно общий принцип проектирования, который относится к отделению спецификации поведения от момента его фактического выполнения.Сравните, например,

myDependency.doThis();

с

myDependency.onEventX += doThis();

В последнем случае нет прямого вызова , что является более гибким.В общем виде инверсия управления относится к схеме наблюдателя , событиям или обратным вызовам .

2.Инверсия зависимостей

Инверсия зависимостей - еще один принцип проектирования.Грубо говоря, это говорит о том, что абстракция более высокого уровня не должна напрямую зависеть от абстракций более низкого уровня;это действительно приводит к разработке, в которой абстракция более высокого уровня не может быть повторно использована без абстракций более низкого уровня.

 class MyHighLevelClass {
     MyLowLevelClass dep = new MyLowLeverClass();
 }

 class App {
     void main() {  new HighLevelClass().doStuff(); }
 }

Здесь MyHighLevelClass не может скомпилироваться без доступа к MyLowLevelClass.Чтобы разорвать эту связь, нам нужно абстрагировать класс низкого уровня с интерфейсом и удалить прямую реализацию.

class MyLowLevelClass implements MyUsefulAbstraction { ... }

class MyHighLevelClass {

    MyUsefulAbstraction dep;

    MyHighLevelClass( MyUsefulAbstraction dep ) {
        this.dep = dep;
    }
}

class App {
     void main() {  new HighLevelClass( new LowLevelClass() ).doStuff(); }
 }

Обратите внимание, что вам не нужно ничего особенного, например, контейнер, для обеспечения инверсии зависимостей, что является принципом.Хорошее чтение: Принцип инверсии зависимости от дяди Боба.

3.Внедрение зависимостей

Теперь идет внедрение зависимостей.Для меня dependency injection = IoC + dependency inversion:

  1. зависимости предоставляются извне, поэтому мы применяем принцип инверсии зависимостей
  2. контейнер устанавливает зависимости (не мы), поэтому мы говорим об инверсии управления

В приведенном выше примере внедрение зависимостей может быть выполнено, если контейнер используется для создания экземпляров объектов и автоматически вводит зависимость в конструктор (мы часто говорим о контейнере DI):

 class App {
     void main() {  DI.getHighLevelObject().doStuff(); }
 }

Обратите внимание, что существуют различные формы инъекций .Также обратите внимание, что с этой точки зрения внедрение сеттера может рассматриваться как форма обратного вызова - контейнер DI создает объект, а затем вызывает метод сеттера.Поток управления эффективно инвертирован.

4.АОП

Строго говоря, АОП имеет мало общего с тремя предыдущими пунктами.Оригинальный документ по AOP является очень общим и представляет идею объединения различных источников (возможно, выраженных на разных языках) для создания работающего программного обеспечения.

Я не буду больше углубляться в АОП.Что здесь важно, так это то, что внедрение зависимостей и AOP эффективно взаимодействуют друг с другом, потому что это делает переплетение очень простым.Если контейнер IoC и внедрение зависимостей используются для абстрагирования создания объектов, контейнер IoC можно легко использовать для создания аспектов перед внедрением зависимостей.В противном случае это потребует специальной компиляции или специального ClassLoader.

Надеюсь, это поможет.

10 голосов
/ 03 апреля 2010

Инъекция зависимости была очень хорошо объяснена в Как объяснить инъекцию зависимости пятилетнему ребенку? :

Когда вы идете и достаете вещи из холодильника дляВы сами можете вызвать проблемы.Вы можете оставить дверь открытой, вы можете получить что-то, что мама или папа не хотят, чтобы вы имели.Возможно, вы даже ищете что-то, чего у нас нет или срок действия которого истек.

Что вам следует делать, так это заявлять о необходимости: «Мне нужно что-нибудь выпить с обедом», и тогда мы позаботимсяу вас есть что-то, когда вы садитесь, чтобы поесть.

AOP - Аспектно-ориентированное программирование - в основном означает, что исходный код, который вы пишете, изменяется с помощью другого кода, основанного на правилах, расположенных ELSEWHERE.Это означает, что вы можете, например, сказать «в качестве первой строки каждого метода я хочу 'log.debug (" ввод method ()")' в центральном месте, и каждый метод, который вы компилируете с этимПравило на месте будет включать эту строку. «Аспект» - это имя просмотра кода другими способами, а не просто от первой строки исходного кода до последней.

Инверсия управления в основном означает, что у вас нетцентральный фрагмент кода, управляющий всем (например, гигантский переключатель в main ()), но имеющий много фрагментов кода, которые «как-то» вызывают. Тема обсуждается в Википедии: http://en.wikipedia.org/wiki/Inversion_of_control

1 голос
/ 09 апреля 2014

Разница между введением зависимости и инверсией управления очень хорошо объяснена в

http://martinfowler.com/articles/dipInTheWild.html

(«Вы имеете в виду инверсию зависимостей, верно?»)

Резюме:

DI о том, как один объект приобретает зависимость. Когда зависимость предоставляется снаружи, тогда система использует DI.

IoC о том, кто инициирует вызов. Если ваш код инициирует звонок, это не IoC, если контейнер / система / библиотека перезванивает в код что вы его предоставили, это IoC.

1 голос
/ 14 мая 2013

Простое сравнение с Spring in Action:

Принимая во внимание, что DI помогает вам отделить ваше приложение объекты друг от друга, АОП помогает вам отделить сквозные проблемы от объекты, на которые они влияют.

1 голос
/ 24 января 2013

позвольте мне сказать вам несколько слов об АОП, надеюсь, это сделает его более простым для понимания. Самым базовым принципом АОП является поиск общих задач / аспектов, которые возвращаются в многие места в коде и не относятся к конкретному бизнесу кода. Например писать в журнал при каждом входе в какую-либо функцию или при создании объекта обернуть его, или отправлять письмо администратору при вызове определенной функции. Таким образом, вместо того, чтобы программисты справились с этим аспектом, не связанным с бизнесом, мы берем его и мы управляем этими аспектами рядом со сценой. Это все основные АОП на 1 ногу ....

1 голос
/ 04 апреля 2010

Все эти три понятия разные, но все они хорошо работают вместе, и приложения Spring часто используют все это сразу. Я приведу вам пример.

Допустим, у нас есть веб-приложение, которое может делать много разных вещей. Мы могли бы создать это приложение разными способами, но один из них - создать класс, отвечающий за выполнение каждой из этих вещей. Нам нужно вызвать и создать эти классы откуда-то. Один из вариантов - создать большой основной класс, который создает одну из этих служб, открывает сокет и передает вызовы этим службам по мере их поступления. К сожалению, мы ушли и создали себе класс Бога, который имеет слишком много логики и слишком много знает о том, как все в нашей программе работает. Если мы что-то изменим в нашей программе, нам, вероятно, понадобится изменить этот класс.

Кроме того, это трудно проверить. Мы не можем тестировать какой-либо класс изолированно, если он работает вокруг создания и вызова других классов напрямую. Модульные тесты становятся намного труднее писать.

Чтобы обойти это, используйте инверсию управления. Мы говорим: «Хорошо, это классы обслуживания. Кто их обслуживает? Не я». Обычно каждый из них определяет интерфейс, такой как LoginService или BillingService. Может быть несколько реализаций этого интерфейса, но вашему приложению все равно. Он просто знает, что может запросить определенную услугу или услугу с определенным именем, и получит что-то приятное.

Внедрение зависимостей позволяет нам соединять все наши маленькие кусочки вместе. Классы имеют доступные поля, аргументы конструктора или методы установки, которые являются ссылками на другие компоненты, к которым им потребуется доступ. Это делает модульное тестирование намного проще. Вы можете создать тестируемый объект, создать в нем ложную или заглушенную зависимость, а затем проверить, правильно ли он себя вел в изоляции.

Теперь наше реальное приложение представляет собой сложную кучу кусочков, которые нужно просто соединить вместе. Есть много способов сделать это, в том числе дать приложению возможность угадать («этот класс требует UserService, я отвечаю только за один класс, реализующий UserService») или тщательно объяснив, как они соединяются вместе в XML или Java. По своей сути Spring - это сервис, который заботится о соединении этих классов.

Теперь мы добрались до АОП. Давайте скажем, что у нас есть все эти классы, которые связаны друг с другом сложными способами. Есть некоторые сквозные проблемы, которые мы могли бы хотеть описать очень общими способами. Например, возможно, вы захотите запустить транзакцию базы данных всякий раз, когда вызывается какая-либо служба, и зафиксировать эту транзакцию, если служба не вызывает исключение. Оказывается, что Spring находится в уникальном положении для выполнения такой задачи. Spring может создавать прокси-классы на лету, которые реализуют любой интерфейс, который нужен вашим классам, и он может обернуть ваш класс в свой прокси. Теперь IoC и внедрение зависимостей, разумеется, не нужны для аспектно-ориентированного программирования, но это чрезвычайно удобный способ сделать это.

...