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

の記事のソースコードを見つけることができます。