Spring First (1): Making Java Development easier (top)

Source: Internet
Author: User

1. Releasing POJOs Energy

Traditional development is how to bind POJOs, if you have developed Java for a long time, then you must have been exposed to the development of EJB. At the time, developing a small function would extend the framework's class or implement its interface. So it's easy to see the skeleton code that hacked into your app in the early Struts,webwork,taperstry framework.

Spring as much as possible to avoid filling in your app with its api.spring never force you to implement a specific spring interface or extend a specific spring class. Instead, there are often no instructions in spring-based applications that you are using spring. In the worst case, the spring annotations are used in the class, but it is still a pojo. Here is a Pojo instance

 Public class Helloworldbean { public String SayHello () {    return ' Hello world ';    }}

As you can see, this is a simple, plain Java class----a pojo. There is no indication that it is a component of spring. Spring's non-aggressive programming model means that this class behaves the same way in spring and non-spring applications.

Although their manifestations are simple, Pojo is very powerful. One way spring makes them strong is by using Di to assemble them. Let's look at how Di keeps objects in the app decoupled from one another.

2. Dependency Injection

  Dependency injection This phrase may sound scary, as if a complex programming technique or design pattern concept is as mysterious as that. But the opposite is true, and Di is not as complex as it sounds. By applying di in your project, you will find that your code will become very simple, easy to understand and test.

How does di work?

Any important application (much more complex than Hello World) is the collaboration of two or more classes to execute a series of business logic. Traditionally, each object has the responsibility to get the object it depends on. This leads to highly coupled and difficult code testing. Here is an example

 public  class  damselrescuingknight implements   Knight {  Rescuedamselquest Quest;  public   Damselrescuingknight () { this . Quest = new      Rescuedamselquest ();  public  void   Embarkonquest () {Quest.embark (); }}    

As you can see, a quest is created in the Damselrescuingknight constructor, a rescuedamselquest, This resulted in the damselrescuingknight and rescuedamselquest tightly coupled and limited the operation of the quest-embarking. What's worse, it's hard to write unit tests for this class. In such a test, you want to be able to evaluate the invocation of the quest ' s embark () method when the Embarkonquest () method is called. Obviously there's no obvious way to achieve that. Unfortunately, Damselrescuingknight will become non-testable.

Coupling is a two-headed monster. On the one hand, tightly coupled code is difficult to test, it is difficult to reuse and understand, it is a typical display of the game of the mole (fixed a bug that will cause one or more bugs to appear). On the other hand, a certain amount of coupling is also necessary. Fully decoupled code can do nothing. To be able to implement useful functionality, a class must somehow know some of the other classes. Coupling is necessary but should be carefully managed.

With Di, the creation of an object's dependencies will be coordinated by a third party. Objects will no longer expect to create or acquire their dependencies, as shown in 1.1, the dependency will be injected into the desired object.

Let's take a look at the braveknight example

 Public class Implements Knight {    private  Quest Quest;      Public braveknight (Quest Quest) {        this. Quest = Quest;    }       Public void embarkonquest () {        quest.embark ();    }}

As you can see, braveknight, unlike Damselresucingknight, did not create its own quest. Instead, the quest is passed in as a constituent parameter. This type of di we call constructor injection.

Moreover, quest is an interface, not a concrete implementation. This allows all interfaces that implement quest to be used here. The Braveknight key point is not to be coupled with any quest specific implementation. It does not care which type of quest the embark is called. As long as it implements the quest interface on the line. This is the most important benefit of di----decoupling.

The most common practice during testing is to wrap the dependencies into a mock implementation. You may not be able to fully test the damselresucingknight due to tight coupling, but it is easy to test braveknight with a mock implementation. As shown below

 Public class braveknighttest {    @Test    publicvoid  knightshouldembarkonquest () {         = Mock (Quest.  Class);         New braveknight (mockquest);        Knight.embarkonquest ();        Verify (Mockquest, Times (1)). Embark ();    }}

Here you use the Mockito framework to mock the object, and with the mock object, you create a new Braveknight instance that is injected into the mock Quest by the constructor. Then call the Embarkonquest () method and ask Mockito to verify that the mock Quest's embark () method is called once. Here is a concrete quest implementation

 Public class Implements Quest {    private  printstream stream;      Public slaydragonquest (PrintStream stream) {        this. stream = stream;    }       Public void Embark () {        stream.println ("embarking on quest to slay the dragon!" );    }}

As you can see, Slaydragonquest is quest specifically implemented, but you may notice that there is a PrintStream object in the Quest constructor, and you may have questions about how to Slaydragonquest to Braveknight? And how does PrintStream give Slaydragonquest?

The behavior of creating related application components is often called assembly (wiring). There are many ways to assemble in spring, but the most common approach is through XML. Here's an XML code

<?XML version= "1.0" encoding= "UTF-8"?><Beansxmlns= "Http://www.springframework.org/schema/beans"Xmlns:xsi= "Http://www.w3.org/2001/XMLSchema-instance"xsi:schemalocation= "Http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsd "><BeanID= "Knight"class= "Com.springinaction.knights.BraveKnight">    <Constructor-argref= "Quest" /></Bean><BeanID= "Quest"class= "Com.springinaction.knights.SlayDragonQuest">    <Constructor-argvalue= "#{t (System). Out}" /></Bean></Beans>

Here, Braveknight and Slaydragonquest are declared as spring beans. In the Braveknight Bean example, a reference to a slaydragonquest bean is passed to the Braveknight constructor as a constructor parameter. At the same time, the Slaydragonquest Bean declaration uses the spring expression language to pass System.out to the Slaydragonquest ' s constructor.

If the XML configuration is inappropriate for your appetite, you may prefer to use Java to achieve the same purpose

  

@Configuration  Public class knightconfig {    @Bean    public  Knight Knight () {        returnnew Braveknight (Quest ());    }    @Bean    public  Quest Quest () {        returnnew  Slaydragonquest (System.out);    }}

This code is equivalent to the XML configuration above. This example simply shows how the bean is assembled in spring. You don't have to worry too much about these details right now, and in a later chapter you'll delve into these configurations. Now everything is well equipped, just how to run the app.

In spring applications, theapplication context is primarily used to load bean definitions and assemble them together. The whole responsibility of Spring application context is to create and assemble objects and use them to construct the application. Spring comes with several application context implementations, the main difference being how to load its configuration.

When using an XML file to declare beans, an appropriate application context selection might be classpathxmlapplicationcontext. This spring context implementation loads the spring context from one or more XML files in the application's classpath. Here's a concrete example.

 public  class   Knightmain { static  void  main (string[] args) throws   Exception {Classpathxmlapplicationcontext context  = new   Classpathxmlapplicationcontext (" meta-inf/spring/knight.xm        L "); Knight Knight  = Context.getbean (Knight.        Class  );            Knight.embarkonquest ();    Context.close (); }}

In this main () method, the spring application context is loaded through knight.xml. The application context is then treated as a factory to fetch the bean with the ID knight. Finally, the Embarkonquest method is called from an object that is referenced as knight. Note that this class does not know the specific implementation of quest, only the Knights.xml file will know the implementation.

Spring First (1): Making Java Development easier (top)

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.