spring and interfaces

后端 未结 9 787
无人及你
无人及你 2020-12-08 14:45

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.

相关标签:
9条回答
  • 2020-12-08 15:13

    Spring won't force you to use interfaces anywhere, it's just good practice. If you have a bean that has a some properties that are interfaces instead of concrete classes, then you can simply switch out some objects with mockups that implement the same interface, which is useful for certain test cases.

    If you use for example the Hibernate support clases, you can define an interface for your DAO, then implement it separately; the advantage of having the interface is that you will be able to configure it using the Spring interceptors, which will allow you to simplify your code; you won't have to write any code cathing HibernateExceptions and closing the session in a finally segment, and you won't have to define any transactions programmatically either, you just configure all that stuff declaratively with Spring.

    When you're writing quick and dirty apps, you can implement some simple DAO using JDBC or some simple framework which you won't end up using in the final version; you will be able to easily switch those components out if they implement some common interfaces.

    0 讨论(0)
  • 2020-12-08 15:16

    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.

    0 讨论(0)
  • 2020-12-08 15:18

    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.

    0 讨论(0)
  • 2020-12-08 15:18

    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.

    0 讨论(0)
  • 2020-12-08 15:24

    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" />
    
    0 讨论(0)
  • 2020-12-08 15:30

    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.

    0 讨论(0)
提交回复
热议问题