简单英语什么是AOP、依赖注入和控制反转

发布于 2024-08-27 13:22:28 字数 69 浏览 8 评论 0原文

我试图理解 AOP、依赖注入和控制反转 SPRING 相关概念,但我很难理解它。

谁能用简单的英语解释一下?

I have tried to understand AOP, Dependency Injection and Inversion of Control SPRING related concepts but I am having hard time understanding it.

Can anyone explain this in simple English ?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

淡忘如思 2024-09-03 13:22:28

我理解您的困惑,我花了一些时间才理解这些概念是如何相互关联的。所以这是我对这一切的(某种程度上个人的)解释:

1。控制反转

控制反转是一个相当通用的设计原则,指的是解耦实际执行时的行为规范。例如,

myDependency.doThis();

myDependency.onEventX += doThis();

后者相比,没有直接调用,更加灵活。就其一般形式而言,控制反转与观察者模式事件回调相关。

2.依赖倒置

依赖倒置是另一个设计原则。粗略地说,它表示高层抽象不应该直接依赖于低层抽象;这确实会导致设计中,如果没有较低级别的抽象,就无法重用较高级别的抽象。

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

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

这里,如果不访问 MyLowLevelClassMyHighLevelClass 就无法编译。为了打破这种耦合,我们需要用接口抽象低级类,并删除直接实例化。

class MyLowLevelClass implements MyUsefulAbstraction { ... }

class MyHighLevelClass {

    MyUsefulAbstraction dep;

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

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

请注意,您不需要任何特殊的东西(例如容器)来强制依赖倒置,这是一个原则。值得一读的是 Uncle Bob 所著的依赖倒置原理

3.依赖注入

现在是依赖注入。对我来说,依赖注入 = IoC + 依赖倒置:

  1. 依赖项是外部提供的,因此我们强制执行依赖倒置原则,
  2. 容器设置依赖项(而不是我们),因此我们谈论控制反转

在上面我提供的示例中,如果使用容器来实例化对象并在构造函数中自动注入依赖项,则可以完成依赖项注入(我们经常谈到 DI 容器):

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

请注意,有各种 注入形式。另请注意,从这个角度来看, setter 注入 可以被视为回调的一种形式 - DI 容器创建对象然后回调 setter。控制流程实际上被颠倒了。

4. AOP

严格来说,AOP 和前面3点关系不大。 关于 AOP 的开创性论文非常通用且现实将各种源代码编织在一起(可能用不同的语言表达)以生成可用软件的想法。

我不会对 AOP 进行更多展开。这里重要的是,依赖注入和 AOP 确实有效地协同工作,因为它使编织变得非常容易。如果使用 IoC 容器和依赖项注入来抽象对象的实例化,则可以轻松地使用 IoC 容器在注入依赖项之前编织各个方面。否则,这将需要特殊的编译或特殊的类加载器。

希望这有帮助。

I understand your confusion and it took me some time to understand how these concepts were related together. So here is my (somehow personal) explanation of all this:

1. Inversion of Control

Inversion of control is a design principle rather generic that refers to the decoupling of the specification of a behavior from when it is actually executed. Compare for instance,

myDependency.doThis();

with

myDependency.onEventX += doThis();

In the latter, there is no direct invocation which is more flexible. In its general form, inversion of control relates to the observer pattern, events, or callbacks.

2. Dependency inversion

Dependency inversion is another design principle. Roughly speaking, it says that higher-level abstraction should not depend directly on lower-level abstractions; this results indeed in a design where higher-level abstraction can not be reused without the lower-level abstractions.

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

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

Here, MyHighLevelClass can not compile without access to MyLowLevelClass. To break this coupling, we need to abstract the low level class with an interface, and remove the direct instantiation.

class MyLowLevelClass implements MyUsefulAbstraction { ... }

class MyHighLevelClass {

    MyUsefulAbstraction dep;

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

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

Note that you don't need anything special like a container to enforce dependency inversion, which is a principle. A good reading is The Dependency Inversion Principle by Uncle Bob.

3. Dependency injection

Now comes dependency injection. To me dependency injection = IoC + dependency inversion:

  1. dependencies are provided externally so we enforce the dependency inversion principle
  2. the container sets the dependencies (not us) so we speak of inversion of control

In the example I provided above, dependency injection can be done if a container is used to instantiate objects and automatically inject the dependency in the constructor (we speak then frequently of DI container):

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

Note that there are various form of injections. Note also that under this perspective, setter injection can be seen as a form of callback -- the DI container creates the object then calls back the setter. The flow of control is effectively inverted.

4. AOP

Strictly speaking, AOP has little to do with the 3 previous points. The seminal paper on AOP is very generic and present the idea of weaving various sources together (possibly expressed with different languages) to produce a working software.

I won't expand more on AOP. What is important here, is that dependency injection and AOP do effectively plays nicely together because it makes the weaving very easy. If an IoC container and dependency injection is used to abstract away the instantiation of objects, the IoC container can easily be used to weave the aspects before injecting the dependencies. This would otherwise requires a special compilation or a special ClassLoader.

Hope this helps.

不即不离 2024-09-03 13:22:28

依赖注入在 如何向 5 岁的孩子解释依赖注入?

当你去拿东西的时候
自己的冰箱,你可以
造成问题。你可能会离开
门打开,你可能会得到一些东西
妈妈或爸爸不想让你这么做
有。您甚至可能正在寻找
一些我们甚至没有的东西
已过期。

你应该做的是陈述一个
需要,“我需要喝点东西
午餐,”然后我们会确保您
当你坐下来时有东西
吃。

AOP - 面向方面的编程 - 基本上意味着您编写的源代码是根据位于其他地方的规则用其他代码修改的。这意味着您可以说“作为每个方法的第一行,我希望在中心位置有一个 'log.debug("entering method()")' 以及您编译的每个方法然后,该规则将包含该行。“方面”是以其他方式查看代码的名称,而不是简单地从第一个源代码行到最后一个代码行,这

基本上意味着您没有控制的核心代码段 。一切(就像 main() 中的一个巨大的开关),但有很多代码“不知何故”被调用。这个主题在维基百科上讨论:http://en.wikipedia.org/wiki/Inversion_of_control

Dependency injection was explained very well in How to explain dependency injection to a 5-year-old?:

When you go and get things out of the
refrigerator for yourself, you can
cause problems. You might leave the
door open, you might get something
Mommy or Daddy doesn't want you to
have. You might even be looking for
something we don't even have or which
has expired.

What you should be doing is stating a
need, "I need something to drink with
lunch," and then we will make sure you
have something when you sit down to
eat.

AOP - Aspect Oriented Programming - basically means that the source you write is modified with other code, based on rules located ELSEWHERE. This means that you can e.g. say "as the first line of every method I want a 'log.debug("entering method()")' in a central place and each and every method you compile with that rule in place will then have that line included. The "aspect" is the name of looking on code in other ways than simply from first source line to last.

Inversion of Control basically means that you do not have a central piece of code controlling everything (like a giant switch in main()) but have a lot of pieces of code that "somehow" get called. The subject is discussed at Wikipedia: http://en.wikipedia.org/wiki/Inversion_of_control

格子衫的從容 2024-09-03 13:22:28

这三个概念都是不同的,但它们都能很好地协同工作,因此 Spring 应用程序经常同时使用它们。我给你举个例子。

假设我们有一个可以执行许多不同操作的 Web 应用程序。我们可以通过多种方式构建这个应用程序,但一种方法是创建一个类来负责完成这些事情。我们需要从某个地方调用并创建这些类。一种选择是有一个大的主类,它创建每个服务之一,打开一个套接字,并在这些服务进入时将调用传递给它们。不幸的是,我们已经为自己创建了一个上帝类,它有方法太多的逻辑并且对我们程序中的所有内容如何工作了解太多。如果我们改变程序的任何内容,我们可能需要修改这个类。

而且,测试也很困难。如果任何类直接实例化和调用其他类,我们就无法单独测试它。单元测试变得越来越难编写。

解决这个问题的一种方法是使用控制反转。我们说“好吧,这些是服务类。谁创建了它们?不是我。”通常,每个服务都定义一个接口,例如 LoginService 或 BillingService。该接口可能有多个实现,但您的应用程序并不关心。它只知道它可以请求某种类型的服务或具有特定名称的服务,并且它会得到一些不错的回报。

依赖注入允许我们将所有的小片段连接在一起。类具有可访问的字段、构造函数参数或 setter 方法,它们是对其需要访问的其他组件的引用。这使得单元测试变得更加容易。您可以创建被测试的对象,向其抛出模拟或存根依赖项,然后测试该对象是否在隔离中正确运行。

现在,我们真正的应用程序是一个复杂的杂乱片段,所有这些片段都需要连接在一起。有很多方法可以实现这一点,包括允许应用程序进行猜测(“这个类需要一个 UserService,而我负责的另一个类则实现了 UserService”)或者仔细解释它们如何在 XML 中连接在一起或Java。 Spring 的核心是一个负责将这些类连接在一起的服务。

现在我们进入 AOP。假设我们拥有所有这些以复杂方式相互连接的类。我们可能希望以非常通用的方式描述一些跨领域的问题。例如,您可能希望在调用任何服务时启动数据库事务,并在服务不引发异常时提交该事务。事实证明,Spring 处于执行此类任务的独特位置。 Spring 可以动态创建代理类来实现您的类所需的任何接口,并且它可以将您的类包装在其代理中。现在,IoC 和依赖注入当然不是面向方面编程所必需的,但它是实现它的一种极其方便的方法。

These three are all different concepts, but they all work well together, and so Spring apps often make use of all of it at once. I'll give you an example.

Let's say that we have a web application that can do many different things. We could construct this application in many ways, but one way is to create a class that is in charge of doing each of these things. We need to invoke and create these classes from somewhere. One option is to have a big main class that creates one of each of these services, opens up a socket, and passes calls to these services as they come in. Unfortunately, we've gone and created ourselves a god class, which has way too much logic and knows way too much about how everything in our program works. If we change anything about our program, we're probably going to need to modify this class.

Also, it's difficult to test. We can't test any class in isolation if it runs around instantiating and invoking the other classes directly. Unit tests become much, much harder to write.

A way to get around this is to use inversion of control. We say "okay, these are service classes. Who instatiates them? Not me." Usually, each one defines an interface, like LoginService or BillingService. There might be more than one implementation of that interface, but your app doesn't care. It just knows that it can ask for a certain kind of a service or a service with a certain name, and it'll get something nice back.

Dependency injection allows us to wire all of our litle pieces together. Classes have accessible fields, constructor arguments, or setter methods that are references to the other components that they'll need to access. That makes unit testing much easier. You can create the object under test, throw a mock or stub dependency at it, and then test that the object behaved correctly in isolation.

Now, our real application is a complex jumble of pieces that all need to be wired together just so. There are many ways to accomplish this, including allowing the application to make guesses ("this class wants a UserService, there is exactly one other class I'm in charge of that implements UserService") or by carefully explaining how they wire together in XML or Java. Spring, at its core, is a service that takes care of wiring these classes together.

Now we get to AOP. Let us say that we have all of these classes that are wired to each other in elaborate ways. There are some cross-cutting concerns that we might want to describe in very generic ways. For instance, perhaps you'd like to start a database transaction whenever any service is invoked, and commit that transaction so long as the service doesn't throw an exception. It turns out that Spring is in a unique position to perform such a task. Spring can create proxy classes on the fly that implement whatever interface your classes need, and it can wrap your class in its proxy. Now, IoC and dependency injection certainly aren't necessary to do aspect-oriented programming, but it's an extremely convenient way to accomplish it.

凉墨 2024-09-03 13:22:28

中很好地解释了依赖注入和控制反转之间的区别

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

(“你的意思是依赖倒置,对吧?”部分)

摘要:

DI 是关于一个对象如何获取依赖关系。当依赖
外部提供,则系统使用DI。

IoC 是关于谁发起调用的。如果您的代码发起调用,
如果容器/系统/库回调到代码,则不是 IoC
你提供的,是 IoC。

The difference between Dependency Injection and Inversion of Control is explained very well in

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

("You mean Dependency Inversion, Right?" section)

The summary:

DI is about how one object acquires a dependency. When a dependency
is provided externally, then the system is using DI.

IoC is about who initiates the call. If your code initiates a call,
it is not IoC, if the container/system/library calls back into code
that you provided it, is it IoC.

狂之美人 2024-09-03 13:22:28

让我告诉你一些关于AOP的知识,希望它能让你更容易理解。
AOP 的基本原则是找到返回的常见任务/方面
代码中的很多地方并不属于代码的具体业务。例如
写入以登录任何函数的每个入口,或者在创建对象时对其进行包装,或者在调用特定函数时向管理员发送电子邮件。
因此,我们不是由程序员来处理这些非业务方面,而是从他们那里获取并
我们在幕后管理这些方面。
AOP 的所有基本功能都在 1 条腿上......

let me tell you some word about AOP, hope it make it simplier to understand.
The very base principle of AOP is finding common tasks/aspects which returns in
many places in the code and dont belong to the concerete business of the code. For example
write to log on every entrance to any function, or when an object is created wrapp it, or send email to admin when calling to specific function.
So instead of the programmers will handle these non businuss aspect we take it from them and
we manage these aspects behond the scene.
That all the basic of AOP on 1 leg....

薄荷梦 2024-09-03 13:22:28

Spring in Action 的简单比较:

而 DI 可以帮助您解耦应用程序
对象之间相互独立,AOP 可以帮助您将横切关注点与对象之间解耦
它们影响的对象。

A simple comparison from Spring in Action:

Whereas DI helps you decouple your application
objects from each other, AOP helps you decouple cross-cutting concerns from the
objects that they affect.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文