After the release of Java 8 with many new features and libraries, Spring 4.x already supports most of them. Some of the new features of Java 8 have no effect on spring and can be used directly, but some new features require spring support. This article will take you through the new Java 8 features that spring 4.0 and 4.1 already support.
Spring 4 supports Java 6, 7, and 8
The Java 8 compiler compiled code that generates a. class file that needs to be run on Java virtual machines of 8 or more. Because of the heavy use of spring on the reflection mechanism and the library of bytecode manipulation functions such as ASM and cglib, it is important to ensure that these libraries are able to understand the new class file generated by Java 8. Spring therefore embeds the ASM, Cglib, and other libraries through the Jar Jar (https://code.google.com/p/jarjar/) into the spring framework, so that spring can support both Java6, Bytecode Code of 7 and 8 without triggering a run-time error.
The spring framework itself is compiled by the Java 8 compiler and is compiled with compile command options that generate Java 6 bytecode. So you can compile applications that run Spring 4.x Java6, 7, or 8来.
Lambda expressions for spring and Java 8
The designer of Java 8 wanted to ensure that it was backwards compatible so that its lambda expression could be used in the old version of the code compiler. Backwards compatibility is achieved by defining a functional interface concept.
Basically, the designers of Java 8 analyzed the existing Java code architecture, noting that many Java programmers use only one method interface to represent the idea of a method. Here is an example of the interface between the JDK and spring that has only one method, the so-called "functional interface."
Functional interfaces in the JDK:
Public interface Runnable {public abstract void run (); Public interface Comparable<t> {public int compareTo (T o);}
Functional interfaces in the spring framework:
Public interface Connectioncallback<t> { T doinconnection (Connection con) throws SQLException, DataAccessException;} public interface rowmapper<t>{ T maprow (ResultSet rs, int rowNum) throws SQLException;}
In Java 8, any functional interface that is passed in as a method parameter or as a method return value can be replaced with a lambda expression. For example, there is a method defined in spring's JdbcTemplate class as follows:
Public <T> list<t> Query (String sql, rowmapper<t> rowmapper) throws DataAccessException
The second parameter of this query method requires an instance of the RowMapper interface. In Java 8 We can write a lambda expression that is passed in as the value of the second parameter.
Don't write the code like this:
Jdbctemplate.query ("SELECT * from Product", new rowmapper<product> () { @Override the public Product Maprow ( ResultSet rs, int rowNum) throws SQLException { Integer id = rs.getint ("id"); String Description = rs.getstring ("description"); Integer quantity = Rs.getint ("Quantity"); BigDecimal Price = Rs.getbigdecimal ("price"); Date availability = Rs.getdate ("Available_date"); Product Product = new product (); Product.setid (ID); Product.setdescription (description); Product.setquantity (quantity); Product.setprice (price); Product.setavailability (availability); return product; }});
We write this:
Jdbctemplate.query ("SELECT * from Queries.products", (RS, RowNum), { Integer id = rs.getint ("id"); String Description = rs.getstring ("description"); Integer quantity = Rs.getint ("Quantity"); BigDecimal Price = Rs.getbigdecimal ("price"); Date availability = Rs.getdate ("Available_date"); Product Product = new product (); Product.setid (ID); Product.setdescription (description); Product.setquantity (quantity); Product.setprice (price); Product.setavailability (availability); return product;});
We note that this code in Java 8 uses lambda expressions, which is much more compact and more concise than the use of anonymous inner classes in previous versions.
All the details that cover the functional interfaces in Java 8 are beyond the scope of this article, and we strongly recommend that you learn more about functional interfaces elsewhere. The key point to convey in this article is that the lambda expression of Java 8 can be passed to a method compiled with Java 7 or earlier JDK that accepts a function interface as a parameter.
Spring's code has many functional interfaces, so lambda expressions are easy to use with spring. Even if the spring framework itself is compiled into the. class file format of Java 6, you can still write application code in Java 8 lambda expressions, compile with the Java 8 compiler, and run on the Java 8 virtual machine, and your app will work as expected.
In short, because the spring framework has actually used a functional interface before Java 8 is formally defined in the functional interface, it is very easy to use lambda expressions in spring.
Time and date APIs for Spring 4 and Java 8
Java developers have always hated the design flaws of the Java.util.Date class, and finally, Java 8 brings a new date and time API that solves the problems that have long been criticized. This new date and time API is worth a full article, so we won't dwell on its details in this article, but focus on the many new classes introduced in the new Java.time package, such as Localdate, LocalTime, and LocalDateTime.
Spring has a Data transformation framework that allows strings and Java data types to be converted to each other. Spring 4 Upgrades The transformation framework to support those classes in the Java 8th and time API. So your code can write this:
@RestControllerpublic class Examplecontroller { @RequestMapping ("/date/{localdate}") Public String Get (@ DateTimeFormat (ISO = ISO. DATE) {localdate localdate) { return localdate.tostring ();} }
In the above example, the get method parameter is the localdate type of Java 8, and Spring 4 can accept a string parameter such as 2014-02-01 and convert it to an instance of Java 8 localdate.
It is important to note that spring is typically used in conjunction with some other libraries to implement specific functions, such as data persistence with Hibernate, and with Jackson to implement the conversion of Java objects and JSON to each other.
While spring 4 supports the Java 8 date and time library, this does not mean that third-party frameworks such as Hibernate and Jackson can support it. At the time of this publication, Hibernate Jira still has an open request HHH-8844 to support the Java 8th and time APIs in hibernate.
Spring 4 and repeating annotations
Java 8 adds support for repeating annotations, and Spring 4 also supports it. In particular, Spring 4 supports the repetition of annotations @scheduled and @propertysource. For example, be aware of the reuse of @propertysource annotations in the following code snippet:
@Configuration @componentscan@enableautoconfiguration@propertysource ("classpath:/example1.properties") @ Propertysource ("Classpath:/example2.properties") public class Application { @Autowired private environment env; @Bean public jdbctemplate template (DataSource DataSource) { System.out.println (Env.getproperty ("Test.prop1 ")); System.out.println (Env.getproperty ("Test.prop2")); return new JdbcTemplate (DataSource); } public static void Main (string[] args) { springapplication.run (application.class, args);} }
Java 8 optional<> and Spring 4.1
Forgetting to check for null references is a common source of bugs in your app code. One way to eliminate nullpointerexceptions is to ensure that the method always returns a non-null value. For example, the following methods:
Public interface Customerrepository extends Crudrepository<customer, long> { /** * Returns the Customer For the specified ID or * null if the value was not found * /Public Customer Findcustomerbyid (String ID);}
Use the following defective code to invoke Customerrepository:
Customer customer = Customerrepository.findcustomerbyid ("123"); Customer.getname (); Get NULL pointer error
The correct wording of this code should be:
Customer customer = Customerrepository.findcustomerbyid ("123"), if (customer! = null) { customer.getname (); Avoid null pointer errors
}
Ideally, if we don't check if a value can be empty, we expect the compiler to find it in time. The Java.util.Optional class allows us to write interfaces like this:
Public interface Customerrepository extends Crudrepository<customer, long> {public Optional<customer > Findcustomerbyid (String ID);}
In this way, the defective version of this code is not compiled, and the developer must explicitly check if the optional type object has values, as follows:
optional<customer> Optional = Customerrepository.findcustomerbyid ("123"), if (Optional.ispresent ()) { Customer customer = Optional.get (); Customer.getname ();}
So the key point of optional is to make sure that a developer does not have to look up Javadoc to know that a method can return null, or that a null value can be passed to a method. Compiler and method signatures help developers know that a value is a optional type. For a detailed description of the optional class, please refer to here.
Spring 4.1 has two ways of supporting Java Optional. Spring's @autowired annotations have a property of "required", which we can then use to put the following code:
@Servicepublic class MyService { @Autowired (required=false) otherservice otherservice; Public dosomething () { if (otherservice! = null) { //Use other service } }}
Replace with:
public class MyService { @Autowired optional<otherservice> otherservice; Public dosomething () { otherservice.ifpresent (S-so { //use S-do something });} }
Another place where you can use optional is the Spring MVC framework, which can be used to indicate that a parameter of a processing method is optional. For example:
@RequestMapping ("/accounts/{accountid}", requestmethod=requestmethod.post) void update (optional<string> AccountId, @RequestBody account)
This code tells spring that its accountid is an optional parameter.
In summary, the Java 8 Optional class simplifies code writing by reducing the flaws associated with null pointers, while Spring supports Java 8 's optional class well.
Discovery mechanism of parameter names
Java 8 supports preserving the parameter names of methods in compiled code. This means that Spring 4 can extract the parameter names from the method, making the SPRINGMVC code more concise. For example:
@RequestMapping ("/accounts/{id}") Public account Getaccount (@PathVariable ("id") String ID)
Can be rewritten as:
@RequestMapping ("/accounts/{id}") Public account Getaccount (@PathVariable String ID)
You can see that we replace @pathvariable ("id") with @pathvariable because Spring 4 can get the parameter name--id from the compiled Java 8 code. As long as the –parameters tag is specified at compile time, the Java 8 compiler writes the parameter name to the. class file. Before Java 8 was released, spring could also extract parameter names from code that was compiled with the-debug option.
In Java 7 and earlier versions, the-debug option does not preserve the parameter names of abstract methods. This can cause problems with the engineering of spring data, which automatically generates its repository implementations based on the Java interface. For example, the interface is as follows:
Interface Customerrepository extends Crudrepository<customer, long> { @Query ("Select C from Customer C where c. LastName =: LastName ") list<customer> findbylastname (@Param (" LastName ") String LastName);}
We can see that findbylastname still needs @param ("LastName"), because Findbylastname is an abstract method, and the-debug option in Java 7 and earlier does not preserve its parameter names. In Java 8, with the –parameters option, Spring data automatically finds the parameter name of the abstract method, and we can rewrite the interface in the example above to:
Interface Customerrepository extends Crudrepository<customer, long> { @Query ("Select C from Customer C where c. LastName =: LastName ") list<customer> Findbylastname (String lastname);}
Here we no longer need @param ("LastName") to make the code more concise and easy to read. So it's a good way to add –parameters markup when compiling code with Java 8.
Summarize
Spring 4 supports Java 6, 7, and 8, and developers are free to write their own application code using Java 6, 7, or 8来. If you are using Java 8, you can use lambda expressions wherever you have a functional interface, making your code more concise and readable.
Java 8 has made improvements to some libraries, such as the new Java.time package and the optional class, and the optional class makes the code written in spring simpler and clearer.
Finally, compiling Java 8 code with the –parameters option preserves the parameter names of the methods at compile time, allowing developers to write more compact spring MVC methods and spring data query methods.
If you're ready to use Java 8 in your project, you'll find that Spring 4 is a great framework to take advantage of the new Java 8 features.
View English original : Spring 4 and Java 8
Spring 4 supported Java 8 new features at a glance