Spring 4.3の新機能
1概要
Spring 4.3リリースでは、コアコンテナ、キャッシング、JMS、Web MVC、そしてフレームワークのテストサブモジュールにいくつかの素晴らしい改良が加えられました。
この記事では、これらの改善点のいくつかについて説明します。
暗黙的なコンストラクタインジェクション
-
Java 8デフォルトインタフェースメソッドのサポート
-
依存関係の改善された解決
-
キャッシュ抽象化の改良
-
構成された
@ RequestMapping
バリアント -
@ RequestScope
、
@ SessionScope
、
@ ApplicationScope
アノテーション -
@ RequestAttribute
および
@ SessionAttribute
アノテーション -
ライブラリ/アプリケーションサーバーのバージョンサポート
-
InjectionPoint
クラス
2暗黙的なコンストラクタインジェクション
次のサービスクラスを考えます。
@Service
public class FooService {
private final FooRepository repository;
@Autowired
public FooService(FooRepository repository) {
this.repository = repository
}
}
ごく一般的なユースケースですが、コンストラクタの
@ Autowired
アノテーションを忘れた場合、明示的に配線を行わない限り、コンテナはデフォルトのコンストラクタを探す例外をスローします。
そのため、4.3では、このような単一コンストラクタのシナリオで明示的な注入アノテーションを指定する必要はもうありません。これは、アノテーションをまったく持たないクラスにとって特に優雅です。
public class FooService {
private final FooRepository repository;
public FooService(FooRepository repository) {
this.repository = repository
}
}
Spring 4.2以前では、Springは
FooService
のデフォルトコンストラクタを見つけることができないため、このBeanに対する次の設定は機能しません。 Spring 4.3は賢く、自動的にコンストラクタを自動配線します。
<beans>
<bean class="com.baeldung.spring43.ctor.FooRepository"/>
<bean class="com.baeldung.spring43.ctor.FooService"/>
</beans>
同様に、
@ Configuration
クラスは歴史的にコンストラクタインジェクションをサポートしていなかったことに気づいたかもしれません。 4.3の時点ではそうなっていて、当然のことながら単一コンストラクタのシナリオでも
@ Autowired
を省略することができます。
@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. Java 8のデフォルトインタフェースメソッドのサポート
Spring 4.3より前は、デフォルトのインターフェースメソッドはサポートされていませんでした。
JDKのJavaBeanイントロスペクターでもデフォルトメソッドをアクセサとして検出しなかったため、これは実装が容易ではありませんでした。 Spring 4.3以降、デフォルトのインターフェースメソッドとして実装されたゲッターとセッターはインジェクション中に識別されます。これは例えばこの例のようにアクセスされたプロパティのための共通のプリプロセッサとしてそれらを使用することを可能にします
public interface IDateHolder {
void setLocalDate(LocalDate localDate);
LocalDate getLocalDate();
default void setStringDate(String stringDate) {
setLocalDate(LocalDate.parse(stringDate,
DateTimeFormatter.ofPattern("dd.MM.yyyy")));
}
}
このBeanは、
stringDate
プロパティがインジェクトされています。
<bean id="dateHolder"
class="com.baeldung.spring43.defaultmethods.DateHolder">
<property name="stringDate" value="15.10.1982"/>
</bean>
デフォルトのインターフェースメソッドで
@ BeforeTransaction
や
@ AfterTransaction
などのテストアノテーションを使用する場合も同様です。 JUnit 5はすでにデフォルトのインターフェースメソッドに関するテストアノテーションをサポートしており、Spring 4.3が先導しています。これで、共通のテストロジックをインタフェースで抽象化し、それをテストクラスで実装することができます。テストのトランザクションの前後にメッセージを記録するテストケース用のインターフェースは次のとおりです。
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");
}
}
アノテーション
@ BeforeTransaction、
@ AfterTransaction
、および
@ Transactional
に関するもう1つの改善点は、アノテーション付きメソッドを
public
にするという要件の緩和です。
** 4依存関係の解決の向上
最新バージョンでは、既存の
ObjectFactory
インタフェースの拡張である
getIfAvailable
や
getIfUnique
などの既存の
ObjectFactory
インタフェースを拡張して、Beanが存在する場合、または単一の候補を特定できる場合にのみ取得します(特に複数の場合は主候補)。マッチング豆)。
@Service
public class FooService {
private final FooRepository repository;
public FooService(ObjectProvider<FooRepository> repositoryProvider) {
this.repository = repositoryProvider.getIfUnique();
}
}
上記のように初期化中にカスタム解決を目的としてそのような
ObjectProvider
ハンドルを使用するか、遅いオンデマンド解決のためにフィールドにハンドルを格納することができます(通常は
ObjectFactory
を使用して行うように)。
5キャッシュ抽象化の改良点
キャッシュ抽象化は、主にCPUとIOが消費する値をキャッシュするために使用されます。特定の使用例では、所与のキーは、特に起動時に、いくつかのスレッド(すなわちクライアント)によって並行して要求されることがある。
同期キャッシュのサポートは現在要求されている長い間要求されている機能です。次のように仮定します。
@Service
public class FooService {
@Cacheable(cacheNames = "foos", sync = true)
public Foo getFoo(String id) { ... }
}
sync = true
属性に注目してください。これは、値が計算されている間、フレームワークに並行スレッドをブロックするよう指示します。これにより、この集中的な操作が同時アクセスの場合に一度だけ呼び出されるようになります。
Spring 4.3では、キャッシュの抽象化も次のように改善されました。
-
キャッシュ関連アノテーション内のSpEL式は、Beanを参照することができる
(つまり、
@beanName.method()
)。
-
ConcurrentMapCacheManager
と
ConcurrentMapCache
は現在、
新しい
storeByValue
属性によるキャッシュエントリのシリアル化。
-
@ Cacheable
、
@ CacheEvict
、
@ CachePut
、および
@ Caching
は、
属性をオーバーライドしたカスタム合成注釈を作成するためのメタ注釈として使用されます。
6. 構成された
@ RequestMapping
バリアント
Spring Framework 4.3では、一般的なHTTPメソッドのマッピングを単純化し、アノテーション付きハンドラメソッドのセマンティクスをよりよく表現するのに役立つ、次のようなメソッドレベルで構成された
@ RequestMapping
アノテーションの変形が導入されています。
-
@ GetMapping
-
@ PostMapping
-
@ PutMapping
-
@ DeleteMapping
-
@ PatchMapping
たとえば、
@ GetMapping
は、
@ RequestMapping(method = RequestMethod.GET)
と言うより短い形式です。次の例は、
@ GetMapping
という注釈を付けて単純化したMVCコントローラを示しています。
@Controller
@RequestMapping("/appointments")
public class AppointmentsController {
private final AppointmentBook appointmentBook;
@Autowired
public AppointmentsController(AppointmentBook appointmentBook) {
this.appointmentBook = appointmentBook;
}
@GetMapping
public Map<String, Appointment> get() {
return appointmentBook.getAppointmentsForToday();
}
}
7.
@ RequestScope
、
@ SessionScope
、
@ ApplicationScope
アノテーション
注釈駆動型コンポーネントまたはJava Configを使用する場合は、
@ RequestScope
、
@ SessionScope
、および
@ ApplicationScope
の各注釈を使用して、コンポーネントを必要なスコープに割り当てることができます。これらのアノテーションはBeanのスコープを設定するだけでなく、スコーププロキシモードを
ScopedProxyMode.TARGET
CLASS.__に設定します。
TARGET
CLASS
モードは、CGLIBプロキシがこのBeanのプロキシとして使用され、より広いスコープであっても他のBeanに確実に挿入できることを意味します。
TARGET
CLASS
モードでは、インターフェースだけでなくクラスもプロキシーできます
_.
_
@RequestScope
@Component
public class LoginAction {
//...
}
@SessionScope
@Component
public class UserPreferences {
//...
}
@ApplicationScope
@Component
public class AppPreferences {
//...
}
8.
@ RequestAttribute
および
@ SessionAttribute
アノテーション
HTTPリクエストのパラメータを
Controller
メソッドにインジェクトするためのさらに2つのアノテーション、つまり
@ RequestAttribute
と
@ SessionAttribute
が登場しました。それらを使用すると、グローバルに(つまり
Controller
の外部で)管理されている既存の属性にアクセスできます。これらの属性の値は、例えば、
javax.servlet.Filter
または
org.springframework.web.servlet.HandlerInterceptor
の登録済みインスタンスによって提供されます。
リクエストを解析してセッションに
login
パラメータを、リクエストに別の
query
パラメータを追加する、次の
HandlerInterceptor
実装を登録したとします。
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);
}
}
そのようなパラメータは、メソッドの引数に対応するアノテーションを付けて
Controller
インスタンスに注入することができます。
@GetMapping
public String get(@SessionAttribute String login,
@RequestAttribute String query) {
return String.format("login = %s, query = %s", login, query);
}
9ライブラリ/アプリケーションサーバーのバージョンサポート
Spring 4.3は、次のライブラリバージョンとサーバー世代をサポートします。
-
Hibernate ORM 5.2(まだ4.2/4.3と5.0/5.1もサポートしています)
3.6今は廃止予定)
** Jackson 2.8(Spring 4.3以降はJackson 2.6まで引き上げられました)
-
OkHttp 3.x(OkHttp 2.xをサポートしています)
-
ネッティ4.1
-
Undertow 1.4
Tomcat 8.5.2および9.0 M6
さらに、Spring 4.3では、更新されたASM 5.1とObjenesis 2.4が
spring-core.jar
に埋め込まれています。
10
インジェクションポイント
InjectionPoint
クラスは、Spring 4.3で導入された新しいクラスで、メソッド/コンストラクタパラメータでもフィールドでも、特定のBeanがインジェクトされる場所に関する情報を提供します。
このクラスを使用して見つけることができる情報の種類は次のとおりです。
-
Field
オブジェクト – あなたは、注入点をラップとして得ることができます。
Beanがインジェクトされている場合は
getField()
メソッドを使用して
Field
オブジェクト
フィールドに
**
MethodParameter
–
getMethodParameter()
メソッドを呼び出すことができます
以下の場合、
MethodParameter
オブジェクトとしてラップされた注入点を取得します。
Beanがパラメータにインジェクトされている
**
Member
–
getMember()
メソッドを呼び出すとエンティティが返されます
Member
オブジェクトにラップされた注入済みBeanを含む
**
Class <?>
– 宣言されたパラメータまたはフィールドの型を取得する
getDeclaredType()を使用して、インジェクトされたBean
**
Annotation[]
–
getAnnotations()__メソッドを使うことで、
注釈を表すAnnotationオブジェクトの配列を取得します
フィールドまたはパラメータに関連付けられている
**
AnnotatedElement
– インジェクションを取得するために
getAnnotatedElement()
を呼び出す
AnnotatedElement
オブジェクトとしてラップされたポイント
このクラスが非常に便利な場合は、それらが属するクラスに基づいて
Logger
Beanを作成したい場合です。
@Bean
@Scope("prototype")
public Logger logger(InjectionPoint injectionPoint) {
return Logger.getLogger(
injectionPoint.getMethodParameter().getContainingClass());
}
クラスごとに異なるロガーが作成されるように、Beanを
prototype
スコープで定義する必要があります。
singleton
Beanを作成して複数の場所に注入すると、Springは最初に見つかった注入ポイントを返します。
それから、Beanを
AppointmentsController
にインジェクトできます。
@Autowired
private Logger logger;
11結論
この記事では、Spring 4.3で導入されたいくつかの新機能について説明しました。
ボイラープレートを排除する便利なアノテーション、依存関係のルックアップとインジェクションの新しい便利な方法、そしてウェブとキャッシュ機能の中のいくつかの実質的な改善をカバーしました。
on GitHub
の記事のソースコードを見つけることができます。