spring and interfaces

2020-02-08 05:36发布

I read all over the place about how Spring encourages you to use interfaces in your code. I don't see it. There is no notion of interface in your spring xml configuration. What part of Spring actually encourages you to use interfaces (other than the docs)?

标签: java spring
9条回答
beautiful°
2楼-- · 2020-02-08 05:48

No one has mention yet that in many occasions won't be necessary to create an interface so that the implementing class can be switched quickly because simply there won't be more than one implementing class.

When interfaces are created without need, classes will be created by pairs (interface plus implementation), adding unnecessary boilerplate interfaces and creating potential dependency confusions because, on XML configuration files, components will be sometimes referenced by its interface and sometimes by its implementation, with no consequences at runtime but being incoherent regarding code conventions.

查看更多
成全新的幸福
3楼-- · 2020-02-08 05:52

You may probably want to try using it for yourself to be better able to see this, it may not be clear from the docs how Spring encourages interface use.

Here are a couple of examples:

  1. Say you're writing a class that needs to read from a resource (e.g., file) that may be referenced in several ways (e.g., in classpath, absolute file path, as a URL etc). You'd want to define a org.springframework.core.io.Resource (interface) property on your class. Then in your Spring configuration file, you simply select the actual implementation class (e.g., org.springframework.core.io.ClassPathResource, org.springframework.core.io.FileSystemResource, org.springframework.core.io.UrlResource etc). Spring is basically functioning as an extremely generic factory.

  2. If you want to take advantage of Spring's AOP integration (for adding transaction interceptors for instance), you'll pretty much need to define interfaces. You define the interception points in your Spring configuration file, and Spring generates a proxy for you, based on your interface.

These are examples I personally have experience with. I'm sure there are much more out there.

查看更多
太酷不给撩
4楼-- · 2020-02-08 05:55

it's easy to generate proxies from interfaces.

if you look at any spring app, you'll see service and persistence interfaces. making that the spring idiom certainly does encourage the use of interfaces. it doesn't get any more explicit than that.

查看更多
干净又极端
5楼-- · 2020-02-08 05:59

The Dependency Inversion Principle explains this well. In particular, figure 4.

A. High level modules should not depend on low level modules. Both should depend upon abstractions.

B. Abstraction should not depend upon details. Details should depend upon abstractions.

Translating the examples from the link above into java:

public class Copy {
    private Keyboard keyboard = new Keyboard(); // concrete dependency
    private Printer printer = new Printer();    // concrete dependency
    public void copy() {
        for (int c = keyboard.read(); c != KeyBoard.EOF) {
            printer.print(c);
        }
    }
}

Now with dependency inversion:

public class Copy {
     private Reader reader; // any dependency satisfying the reader interface will work
     private Writer writer; // any dependency satisfying the writer interface will work
     public void copy() {
        for (int c = reader.read(); c != Reader.EOF) {
            writer.write(c);
        }
     }
     public Copy(Reader reader, Writer writer) {
         this.reader = reader;
         this.writer = writer;
     }
}

Now Copy supports more than just copying from a keyboard to a printer.

It is capable of copying from any Reader to any Writer without requiring any modifications to its code.

And now with Spring:

<bean id="copy" class="Copy">
    <constructor-arg ref="reader" />
    <constructor-arg ref="writer" />
</bean>

<bean id="reader" class="KeyboardReader" />
<bean id="writer" class="PrinterWriter" />

or perhaps:

<bean id="reader" class="RemoteDeviceReader" />
<bean id="writer" class="DatabaseWriter" />
查看更多
别忘想泡老子
6楼-- · 2020-02-08 05:59

If you don't use interfaces you risk an autowiring failure: Sometime Spring creates a Proxy class for a Bean. This Proxy class is not a child class of the service implementation but it re-implements all of its interfaces. Spring will try to autowire instances of this Bean, however this Proxy class is incompatible with the Bean class. So declaring a field with Bean class can lead to "unsafe field assignement" exceptions.

You cannot reasonably know when Spring is going to Proxy a service (nor should you), so to protect yourself against those surprises, your best move is to declare an interface and use this interface when declaring autowired fields.

查看更多
▲ chillily
7楼-- · 2020-02-08 06:01

When you define an interface for your classes, it helps with dependency injection. Your Spring configuration files don't have anything about interfaces in them themselves -- you just put in the name of the class.

But if you want to inject another class that offers "equivalent" functionality, using an interface really helps.

For example, saying you've got a class that analyzes a website's content, and you're injecting it with Spring. If the classes you're injecting it into know what the actual class is, then in order to change it out you'll have to change a whole lot of code to use a different concrete class. But if you created an Analyzer interface, you could just as easily inject your original DefaultAnalyzer as you could a mocked up DummyAnalyzer or even another one that does essentially the same thing, like a PageByPageAnalyzer or anything else. In order to use one of those, you just have to change the classname you're injecting in your Spring config files, rather than go through your code changing classes around.

It took me about a project and a half before I really started to see the usefulness. Like most things (in enterprise languages) that end up being useful, it seems like a pointless addition of work at first, until your project starts to grow and then you discover how much time you saved by doing a little bit more work up front.

查看更多
登录 后发表回答