Wat is er nieuw in Spring 4.3?

1. Overzicht

De Spring 4.3-release bracht een aantal mooie verfijningen met zich mee in de kerncontainer, caching, JMS, Web MVC en test-submodules van het framework.

In dit bericht bespreken we enkele van deze verbeteringen, waaronder:

  • Impliciete constructorinjectie
  • Ondersteuning voor standaard Java 8-interfacemethoden
  • Verbeterde oplossing van afhankelijkheden
  • Cache abstractie verfijningen
  • Samengesteld @RequestMapping Varianten
  • @Requestscope, @Sessionscope, @Applicationscope Annotaties
  • @RequestAttribute en @SessionAttribute annotaties
  • Ondersteuning voor bibliotheken / applicatieservers
  • de InjectionPoint klasse

2. Impliciete constructorinjectie

Overweeg de volgende serviceklasse:

@Service openbare klasse FooService {privé definitieve FooRepository-repository; @Autowired openbare FooService (FooRepository-repository) {this.repository = repository}}

Een vrij algemeen gebruik, maar als u het @Autowired annotatie op de constructor, zal de container een uitzondering genereren op zoek naar een standaard constructor, tenzij u expliciet de bedrading doet.

Dus vanaf 4.3 hoeft u niet langer een expliciete injectie-annotatie op te geven in een dergelijk scenario met één constructor. Dit is vooral elegant voor klassen die helemaal geen annotaties bevatten:

openbare klasse FooService {privé definitieve FooRepository-repository; openbare FooService (FooRepository-repository) {this.repository = repository}}

In Spring 4.2 en lager werkt de volgende configuratie voor deze bean niet, omdat Spring geen standaardconstructor kan vinden voor FooService. Spring 4.3 is slimmer en zal de constructor automatisch bedraden:

Evenzo heeft u dat misschien gemerkt @Configuratie Klassen ondersteunden historisch gezien geen constructorinjectie. Vanaf 4.3 doen ze dat, en ze laten natuurlijk weglaten toe @Autowired ook in een scenario met één constructor:

@Configuration openbare klasse FooConfiguration {privé definitieve FooRepository-repository; openbare FooConfiguration (FooRepository-repository) {this.repository = repository; } @Bean public FooService fooService () {retourneer nieuwe FooService (this.repository); }}

3. Ondersteuning voor standaard Java 8-interfacemethoden

Vóór Spring 4.3 werden standaard interfacemethoden niet ondersteund.

Dit was niet eenvoudig te implementeren omdat zelfs de JavaBean-introspector van JDK geen standaardmethoden als accessors detecteerde. Sinds Spring 4.3 worden getters en setters geïmplementeerd als standaard interfacemethoden geïdentificeerd tijdens injectie, waardoor ze bijvoorbeeld kunnen worden gebruikt als gewone preprocessors voor geopende eigenschappen, zoals in dit voorbeeld:

openbare interface IDateHolder {void setLocalDate (LocalDate localDate); LocalDate getLocalDate (); standaard ongeldig setStringDate (String stringDate) {setLocalDate (LocalDate.parse (stringDate, DateTimeFormatter.ofPattern ("dd.MM.yyyy"))); }} 

Deze boon kan nu de stringDate eigendom geïnjecteerd:

Hetzelfde geldt voor het gebruik van testannotaties zoals @BeforeTransaction en @AfterTransaction op standaard interfacemethoden. JUnit 5 ondersteunt al zijn testannotaties op standaard interfacemethoden, en Spring 4.3 volgt het voorbeeld. Nu kunt u algemene testlogica in een interface abstraheren en deze in testklassen implementeren. Hier is een interface voor testgevallen die berichten voor en na transacties in tests registreert:

openbare interface ITransactionalTest {Logger log = LoggerFactory.getLogger (ITransactionalTest.class); @BeforeTransaction default void beforeTransaction () {log.info ("Voordat transactie wordt geopend"); } @AfterTransaction standaard ongeldig afterTransaction () {log.info ("Na het sluiten van de transactie"); }}

Een andere verbetering met betrekking tot annotaties @BeforeTransaction,@AfterTransaction en @Transactional is de versoepeling van de eis die de geannoteerde methoden zouden moeten zijn openbaar - nu kunnen ze elk zichtbaarheidsniveau hebben.

4. Verbeterde oplossing van afhankelijkheden

De nieuwste versie introduceert ook de ObjectProvider, een uitbreiding van het bestaande ObjectFactory interface met handige handtekeningen zoals getIfAvailable en getIfUnique om een ​​boon alleen op te halen als deze bestaat of als een enkele kandidaat kan worden bepaald (in het bijzonder: een primaire kandidaat in het geval van meerdere bijpassende bonen).

@Service openbare klasse FooService {privé definitieve FooRepository-repository; openbare FooService (ObjectProvider repositoryProvider) {this.repository = repositoryProvider.getIfUnique (); }}

U kunt dergelijke gebruiken ObjectProvider handle voor aangepaste resolutiedoeleinden tijdens initialisatie, zoals hierboven weergegeven, of sla de handle op in een veld voor een late on-demand oplossing (zoals u gewoonlijk doet met een ObjectFactory).

5. Cache abstractie verfijningen

De cache-abstractie wordt voornamelijk gebruikt om waarden in de cache op te slaan die CPU en IO verbruiken. In bepaalde gebruikssituaties kan een bepaalde sleutel worden aangevraagd door verschillende threads (d.w.z. clients) parallel, vooral bij het opstarten. Gesynchroniseerde cache-ondersteuning is een langgevraagde functie die nu is geïmplementeerd. Veronderstel het volgende:

@Service openbare klasse FooService {@Cacheable (cacheNames = "foos", sync = true) openbare Foo getFoo (String-id) {...}}

Let op de sync = true attribuut dat het framework vertelt om gelijktijdige threads te blokkeren terwijl de waarde wordt berekend. Dit zorgt ervoor dat deze intensieve bewerking slechts één keer wordt aangeroepen in geval van gelijktijdige toegang.

Spring 4.3 verbetert ook de caching-abstractie als volgt:

  • SpEL-expressies in cachegerelateerde annotaties kunnen nu verwijzen naar bonen (d.w.z. @ beanName.method ()).
  • ConcurrentMapCacheManager en ConcurrentMapCache ondersteunen nu de serialisering van cache-items via een nieuw storeByValue attribuut.
  • @Cacheable, @CacheEvict, @CachePut, en @Caching kunnen nu worden gebruikt als meta-annotaties om op maat samengestelde annotaties te maken met attribuutoverschrijvingen.

6. Samengesteld @RequestMapping Varianten

Spring Framework 4.3 introduceert de volgende samengestelde varianten van het @RequestMapping annotatie die helpt om toewijzingen voor veelgebruikte HTTP-methoden te vereenvoudigen en de semantiek van de geannoteerde handlermethode beter tot uitdrukking te brengen.

  • @GetMapping
  • @PostMapping
  • @PutMapping
  • @DeleteMapping
  • @PatchMapping

Bijvoorbeeld, @GetMapping is een kortere vorm van zeggen @RequestMapping (methode = RequestMethod.GET). Het volgende voorbeeld toont een MVC-controller die is vereenvoudigd met een samengesteld @GetMapping annotatie.

@Controller @RequestMapping ("/ afspraken") openbare klas AppointmentsController {privé laatste AppointmentBook afspraakBook; @Autowired openbare AppointmentsController (AppointmentBook afspraakBook) {this.appointmentBook = afspraakBook; } @GetMapping openbare kaart get () {terug afspraakBook.getAppointmentsForToday (); }}

7. @RequestScope, @SessionScope, @ApplicationScope Annotaties

Bij gebruik van annotatiegestuurde componenten of Java Config, de @RequestScope, @SessionScope en @ApplicationScope annotaties kunnen worden gebruikt om een ​​component aan het vereiste bereik toe te wijzen. Deze annotaties stellen niet alleen het bereik van de bean in, maar stellen ook de scoped proxymodus in op ScopedProxyMode.TARGET_CLASS.

TARGET_CLASS mode betekent dat CGLIB-proxy wordt gebruikt voor proxy van deze bean en ervoor zorgt dat deze in elke andere bean kan worden geïnjecteerd, zelfs met een bredere scope. TARGET_CLASS modus maakt proxy niet alleen voor interfaces mogelijk, maar ook voor klassen.

@RequestScope @Component openbare klasse LoginAction {// ...}
@SessionScope @Component openbare klasse Gebruikersvoorkeuren {// ...}
@ApplicationScope @Component openbare klasse AppPreferences {// ...}

8. @RequestAttribute en @SessionAttribute Annotaties

Nog twee annotaties voor het injecteren van parameters van het HTTP-verzoek in Controller methoden verschenen namelijk @RequestAttribute en @SessionAttribute. Ze geven u toegang tot enkele reeds bestaande attributen, die wereldwijd worden beheerd (d.w.z. buiten het Controller). De waarden voor deze attributen kunnen bijvoorbeeld worden geleverd door geregistreerde instanties van javax.servlet.Filter of org.springframework.web.servlet.HandlerInterceptor.

Stel dat we het volgende hebben geregistreerd HandlerInterceptor implementatie die het verzoek parseert en toevoegt Log in parameter voor de sessie en nog een vraag parameter naar een verzoek:

openbare klasse ParamInterceptor breidt HandlerInterceptorAdapter {@Override public boolean preHandle uit (HttpServletRequest-verzoek, HttpServletResponse-antwoord, Objecthandler) gooit Uitzondering {request.getSession (). setAttribute ("login", "john"); request.setAttribute ("query", "facturen"); retourneer super.preHandle (verzoek, antwoord, handler); }}

Dergelijke parameters kunnen worden geïnjecteerd in een Controller instantie met bijbehorende annotaties op methode-argumenten:

@GetMapping public String get (@SessionAttribute String login, @RequestAttribute String query) {return String.format ("login =% s, query =% s", login, query); }

9. Ondersteuning voor bibliotheken / applicatieservers

Spring 4.3 ondersteunt de volgende bibliotheekversies en servergeneraties:

  • Slaapstand ORM 5.2 (ondersteunt nog steeds 4.2 / 4.3 en 5.0 / 5.1, terwijl 3.6 nu verouderd is)
  • Jackson 2.8 (minimum verhoogd naar Jackson 2.6+ vanaf voorjaar 4.3)
  • OkHttp 3.x (ondersteunt OkHttp 2.x nog steeds naast elkaar)
  • Netty 4.1
  • Undertow 1.4
  • Tomcat 8.5.2 en 9.0 M6

Bovendien integreert Spring 4.3 de bijgewerkte ASM 5.1 en Objenesis 2.4 in spring-core.jar.

10. InjectionPoint

De InjectionPoint class is een nieuwe klasse geïntroduceerd in Spring 4.3 die geeft informatie over plaatsen waar een bepaalde boon wordt geïnjecteerd, of het nu een method / constructor-parameter of een veld is.

De soorten informatie die u met deze klasse kunt vinden, zijn:

  • Veld object - u kunt het punt van injectie verpakken als een Veld object met behulp van de getField () methode als de boon in een veld wordt geïnjecteerd
  • MethodParameter - je kan bellen getMethodParameter () methode om het injectiepunt te verkrijgen verpakt als een MethodParameter object als de boon in een parameter wordt geïnjecteerd
  • Lid - bellen getMember () methode retourneert de entiteit met de geïnjecteerde boon gewikkeld in een Lid voorwerp
  • Klasse - verkrijg het aangegeven type van de parameter of het veld waarin de boon is geïnjecteerd, met behulp van getDeclaredType ()
  • Annotatie [] - door de getAnnotations () methode, kunt u een array van annotatieobjecten ophalen die de annotaties vertegenwoordigen die bij het veld of de parameter horen
  • AnnotatedElement - bellen getAnnotatedElement () om het injectiepunt als een AnnotatedElement voorwerp

Een geval waarin deze klasse erg handig is, is wanneer we willen creëren Logger bonen op basis van de klasse waartoe ze behoren:

@Bean @Scope ("prototype") openbare Logger-logger (InjectionPoint injectionPoint) {return Logger.getLogger (injectionPoint.getMethodParameter (). GetContainingClass ()); }

De boon moet worden gedefinieerd met een voorlopig ontwerp scope zodat er voor elke klasse een andere logger wordt aangemaakt. Als u een singleton boon en injecteer op meerdere plaatsen, de Spring keert terug naar het eerste aangetroffen injectiepunt.

Dan kunnen we de boon in ons spuiten AfsprakenController:

@Autowired privé Logger-logger;

11. Conclusie

In dit artikel hebben we enkele van de nieuwe functies besproken die zijn geïntroduceerd in Spring 4.3.

We hebben nuttige annotaties behandeld die standaardplaat elimineren, nieuwe handige methoden voor het opzoeken en injecteren van afhankelijkheden en verschillende substantiële verbeteringen binnen het web en cachefaciliteiten.

Je kunt de broncode voor het artikel vinden op GitHub.