Was ist neu in Spring 4.3?

Was ist neu im Frühjahr 4.3?

1. Überblick

Die Veröffentlichung von Spring 4.3 brachte einige nette Verbesserungen für Core Container, Caching, JMS, Web MVC und das Testen von Submodulen des Frameworks.

In diesem Beitrag werden wir einige dieser Verbesserungen diskutieren, einschließlich:

  • Implizite Konstruktorinjektion

  • Unterstützung für Java 8-Standardschnittstellenmethoden

  • Verbesserte Auflösung von Abhängigkeiten

  • Verfeinerungen der Cache-Abstraktion

  • Zusammengesetzte@RequestMapping Varianten

  • @Requestscope, @Sessionscope, @Applicationscope Annotations

  • Anmerkungen zu@RequestAttribute und@SessionAttribute

  • Libraries/Application Servers Versions Support

  • die KlasseInjectionPoint

2. Implizite Konstruktorinjektion

Betrachten Sie die folgende Serviceklasse:

@Service
public class FooService {

    private final FooRepository repository;

    @Autowired
    public FooService(FooRepository repository) {
        this.repository = repository
    }
}

Ein recht häufiger Anwendungsfall. Wenn Sie jedoch die Annotation@Autowiredim Konstruktor vergessen, löst der Container eine Ausnahme aus, die nach einem Standardkonstruktor sucht, es sei denn, Sie führen die Verkabelung explizit durch.

Ab 4.3 müssen Sie in einem solchen Ein-Konstruktor-Szenario keine explizite Injection-Annotation mehr angeben. Dies ist besonders elegant für Klassen, die überhaupt keine Anmerkungen enthalten:

public class FooService {

    private final FooRepository repository;

    public FooService(FooRepository repository) {
        this.repository = repository
    }
}

In Spring 4.2 und niedriger funktioniert die folgende Konfiguration für diese Bean nicht, da Spring keinen Standardkonstruktor fürFooService finden kann. Spring 4.3 ist intelligenter und verdrahtet den Konstruktor automatisch:


    
    

In ähnlicher Weise haben Sie möglicherweise bemerkt, dass die Klassen von@Configurationin der Vergangenheit die Konstruktorinjektion nicht unterstützten. Ab 4.3 ist dies der Fall und sie erlauben natürlich auch das Weglassen von@Autowired in einem Einzelkonstruktorszenario:

@Configuration
public class FooConfiguration {

    private final FooRepository repository;

    public FooConfiguration(FooRepository repository) {
        this.repository = repository;
    }

    @Bean
    public FooService fooService() {
        return new FooService(this.repository);
    }
}

3. Unterstützung für Java 8-Standardschnittstellenmethoden

Vor Spring 4.3 wurden Standardschnittstellenmethoden nicht unterstützt.

Dies war nicht einfach zu implementieren, da selbst der JavaBean-Introspector von JDK keine Standardmethoden als Zugriffsmethoden erkannte. Seit Spring 4.3 werden Getter und Setter, die als Standardschnittstellenmethoden implementiert sind, während der Injektion identifiziert, sodass sie beispielsweise als allgemeine Präprozessoren für aufgerufene Eigenschaften verwendet werden können, wie in folgendem Beispiel:

public interface IDateHolder {

    void setLocalDate(LocalDate localDate);

    LocalDate getLocalDate();

    default void setStringDate(String stringDate) {
        setLocalDate(LocalDate.parse(stringDate,
          DateTimeFormatter.ofPattern("dd.MM.yyyy")));
    }

}

Dieser Bean kann jetzt die EigenschaftstringDateinjiziert werden:


    

Gleiches gilt für die Verwendung von Testanmerkungen wie@BeforeTransaction und@AfterTransaction bei Standardschnittstellenmethoden. JUnit 5 unterstützt bereits seine Testanmerkungen für Standardschnittstellenmethoden, und Spring 4.3 folgt diesem Beispiel. Jetzt können Sie allgemeine Testlogik in einer Schnittstelle abstrahieren und in Testklassen implementieren. Hier ist eine Schnittstelle für Testfälle, die Nachrichten vor und nach Transaktionen in Tests protokolliert:

public interface ITransactionalTest {

    Logger log = LoggerFactory.getLogger(ITransactionalTest.class);

    @BeforeTransaction
    default void beforeTransaction() {
        log.info("Before opening transaction");
    }

    @AfterTransaction
    default void afterTransaction() {
        log.info("After closing transaction");
    }

}

Eine weitere Verbesserung in Bezug auf Annotationen@BeforeTransaction,@AfterTransaction und@Transactional ist die Lockerung der Anforderung, dass die annotierten Methodenpublic sein sollten - jetzt können sie eine beliebige Sichtbarkeitsstufe haben.

4. Verbesserte Auflösung von Abhängigkeiten

Die neueste Version führt auchObjectProvider ein, eine Erweiterung der vorhandenenObjectFactory-Schnittstelle mit praktischen Signaturen wiegetIfAvailable undgetIfUnique, um eine Bean nur dann abzurufen, wenn sie vorhanden ist oder wenn a Es kann ein einzelner Kandidat bestimmt werden (insbesondere: ein Hauptkandidat bei mehreren übereinstimmenden Beans).

@Service
public class FooService {

    private final FooRepository repository;

    public FooService(ObjectProvider repositoryProvider) {
        this.repository = repositoryProvider.getIfUnique();
    }
}

Sie können das Handle eines solchenObjectProviderfür benutzerdefinierte Auflösungszwecke während der Initialisierung wie oben gezeigt verwenden oder das Handle in einem Feld für eine späte On-Demand-Auflösung speichern (wie Sie es normalerweise mit einemObjectFactory tun).

5. Verfeinerungen der Cache-Abstraktion

Die Cache-Abstraktion wird hauptsächlich zum Zwischenspeichern von CPU- und E / A-belasteten Werten verwendet. In bestimmten Anwendungsfällen kann ein bestimmter Schlüssel von mehreren Threads angefordert werden (d. H. Clients) parallel, insbesondere beim Start. Synchronisierte Cache-Unterstützung ist eine seit langem angeforderte Funktion, die jetzt implementiert wurde. Es sei folgendes angenommen:

@Service
public class FooService {

    @Cacheable(cacheNames = "foos", sync = true)
    public Foo getFoo(String id) { ... }

}

Beachten Sie das Attributsync = true, das das Framework anweist, alle gleichzeitigen Threads zu blockieren, während der Wert berechnet wird. Dadurch wird sichergestellt, dass diese intensive Operation bei gleichzeitigem Zugriff nur einmal aufgerufen wird.

Spring 4.3 verbessert auch die Caching-Abstraktion wie folgt:

  • SpEL-Ausdrücke in Cache-bezogenen Annotationen können sich jetzt auf Beans beziehen (d. H. @beanName.method()).

  • ConcurrentMapCacheManager undConcurrentMapCache unterstützen jetzt die Serialisierung von Cache-Einträgen über ein neuesstoreByValue-Attribut.

  • @Cacheable,@CacheEvict,@CachePut und@Caching können jetzt als Meta-Annotationen verwendet werden, um benutzerdefinierte zusammengesetzte Annotationen mit Attributüberschreibungen zu erstellen.

6. Zusammengesetzte@RequestMapping Varianten

Spring Framework 4.3 führt die folgenden auf Methodenebene zusammengesetzten Varianten der Annotation@RequestMappingein, die dazu beitragen, die Zuordnungen für gängige HTTP-Methoden zu vereinfachen und die Semantik der mit Annotationen versehenen Handler-Methode besser auszudrücken.

  • @ GetMapping

  • @ PostMapping

  • @ PutMapping

  • @ DeleteMapping

  • @PatchMapping

Zum Beispiel ist@GetMapping eine kürzere Form,@RequestMapping(method = RequestMethod.GET) zu sagen. Das folgende Beispiel zeigt einen MVC-Controller, der mit einer zusammengesetzten@GetMapping-Annotation vereinfacht wurde.

@Controller
@RequestMapping("/appointments")
public class AppointmentsController {

    private final AppointmentBook appointmentBook;

    @Autowired
    public AppointmentsController(AppointmentBook appointmentBook) {
        this.appointmentBook = appointmentBook;
    }

    @GetMapping
    public Map get() {
        return appointmentBook.getAppointmentsForToday();
    }
}

7. @RequestScope,@SessionScope,@ApplicationScope Anmerkungen

Bei Verwendung von annotationsgesteuerten Komponenten oder Java Config können die Annotationen@RequestScope,@SessionScope und@ApplicationScope verwendet werden, um eine Komponente dem erforderlichen Bereich zuzuweisen. Diese Anmerkungen legen nicht nur den Bereich der Bean fest, sondern auch den Proxy-Modus mit Gültigkeitsbereich aufScopedProxyMode.TARGET_CLASS.

TARGET_CLASS-Modus bedeutet, dass der CGLIB-Proxy zum Proxying dieser Bean verwendet wird und sichergestellt wird, dass sie in jede andere Bean injiziert werden kann, auch in einem breiteren Bereich. Der ModusTARGET_CLASS ermöglicht das Proxying nicht nur für Schnittstellen, sondern auch für Klassen.

@RequestScope
@Component
public class LoginAction {
    // ...
}
@SessionScope
@Component
public class UserPreferences {
    // ...
}
@ApplicationScope
@Component
public class AppPreferences {
    // ...
}

8. Anmerkungen zu@RequestAttribute und@SessionAttribute

Es wurden zwei weitere Anmerkungen zum Einfügen von Parametern der HTTP-Anforderung inController-Methoden angezeigt, nämlich@RequestAttribute und@SessionAttribute. Sie ermöglichen Ihnen den Zugriff auf einige bereits vorhandene Attribute, die global verwaltet werden (d. H. außerhalb derController). Die Werte für diese Attribute können beispielsweise durch registrierte Instanzen vonjavax.servlet.Filter oderorg.springframework.web.servlet.HandlerInterceptor bereitgestellt werden.

Angenommen, wir haben die folgende Implementierung vonHandlerInterceptorregistriert, die die Anforderung analysiert und der Sitzung den Parameterloginund der Anforderung einen weiteren Parameterqueryhinzufügt:

public class ParamInterceptor extends HandlerInterceptorAdapter {

    @Override
    public boolean preHandle(HttpServletRequest request,
      HttpServletResponse response, Object handler) throws Exception {
        request.getSession().setAttribute("login", "john");
        request.setAttribute("query", "invoices");
        return super.preHandle(request, response, handler);
    }

}

Solche Parameter können mit entsprechenden Anmerkungen zu Methodenargumenten in eineController-Instanz eingefügt werden:

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

9. Libraries/Application Servers Versions Support

Spring 4.3 unterstützt die folgenden Bibliotheksversionen und Servergenerationen:

  • Hibernate ORM 5.2 (unterstützt auch weiterhin 4.2 / 4.3 und 5.0 / 5.1, wobei 3.6 jetzt veraltet ist)

  • Jackson 2.8 (Minimum angehoben auf Jackson 2.6+ ab Frühjahr 4.3)

  • OkHttp 3.x (unterstützt weiterhin OkHttp 2.x nebeneinander)

  • Netty 4.1

  • Undertow 1.4

  • Tomcat 8.5.2 sowie 9.0 M6

Darüber hinaus bettet Spring 4.3 das aktualisierte ASM 5.1 und Objenesis 2.4 inspring-core.jar ein.

10. InjectionPoint

Die KlasseInjectionPoint ist eine neue Klasse, die in Spring 4.3 eingeführt wurde undprovides information about places where a particular bean gets injected ist, unabhängig davon, ob es sich um einen Methoden- / Konstruktorparameter oder ein Feld handelt.

Die Arten von Informationen, die Sie mit dieser Klasse finden können, sind:

  • Field Objekt - Sie können den Injektionspunkt alsField Objekt erhalten, indem Sie diegetField() Methode verwenden, wenn die Bean in ein Feld injiziert wird

  • MethodParameter - Sie können die MethodegetMethodParameter() aufrufen, um den alsMethodParameter-Objekt umschlossenen Injektionspunkt zu erhalten, wenn die Bean in einen Parameter injiziert wird

  • Member - Wenn Sie die MethodegetMember() aufrufen, wird die Entität zurückgegeben, die die injizierte Bean enthält, die in einMember-Objekt eingeschlossen ist

  • Class<?> - Ermittelt mitgetDeclaredType() den deklarierten Typ des Parameters oder Felds, in das die Bean injiziert wurde

  • Annotation[] - Mit der MethodegetAnnotations() können Sie ein Array von Annotation-Objekten abrufen, die die dem Feld oder Parameter zugeordneten Annotationen darstellen

  • AnnotatedElement - Rufen SiegetAnnotatedElement() auf, um den Injektionspunkt alsAnnotatedElement-Objekt zu verpacken

Ein Fall, in dem diese Klasse sehr nützlich ist, ist, wenn wirLogger Beans basierend auf der Klasse erstellen möchten, zu der sie gehören:

@Bean
@Scope("prototype")
public Logger logger(InjectionPoint injectionPoint) {
    return Logger.getLogger(
      injectionPoint.getMethodParameter().getContainingClass());
}

Die Bean muss mit dem Gültigkeitsbereichprototypedefiniert werden, damit für jede Klasse ein anderer Logger erstellt wird. Wenn Sie einesingleton-Bohne erstellen und an mehreren Stellen injizieren, gibt die Feder den ersten gefundenen Injektionspunkt zurück.

Dann können wir die Bohne in unsereAppointmentsController injizieren:

@Autowired
private Logger logger;

11. Fazit

In diesem Artikel haben wir einige der neuen Funktionen besprochen, die mit Spring 4.3 eingeführt wurden.

Wir haben nützliche Anmerkungen behandelt, die das Boilerplate eliminieren, neue hilfreiche Methoden zur Suche und Injektion von Abhängigkeiten sowie einige wesentliche Verbesserungen innerhalb der Web- und Caching-Funktionen.

Sie finden den Quellcode für den Artikelon GitHub.