なぜ我々は、一般的に安全のSpring Beanのスレッドを使うのか?
春の豆でデフォルトのスコープ内に作成すると、そのオブジェクトが作成することで、シングルトンである単一の例を、次の、我々はこれらのBeanを使用する場合、我々は、多くの場合、サービス、DAOとコントローラを使用すると、ほとんどの場合は、同様のツールに基づいていますフォームが、これらのBeanのメソッドの呼び出しは、Beanは財産、ステータスの変更を持っていないので、スレッドセーフである無マルチスレッド競争が、ありません。
我々は、これらのBeanスレッドセーフを確保する方法のプロパティを変更したい場合は?
プロトタイプの範囲によって
範囲は、プロトタイプに設定されている場合、対象となるたびに、オブジェクトを再構築しますので、特性(メンバ変数)は、スレッド固有のオブジェクトである、スレッドセーフです。しかし、そのようなマルチオブジェクトの作成と破壊は、多くのメモリを占有し、システムリソースを消費しますが、次のようにThreadLocalをお勧めします。
ThreadLocalのを使用することにより
同期オブジェクトのプロパティは、他のスレッドで共有する必要がないときは、あなただけのことを確認する必要がありますスレッド閉じ自体、他のスレッドによって変更されることなく使用します
原則Threadloca
デモ:
各クラスではThreadLocalの共有変数の要求は、フィルタにより、インターセプタは認証成功を共有しました。印刷フィルタ値のThreadLocal、インターセプターと印刷前の設定値にThreadLocalは、メモリリークを回避するために、迎撃後のThreadLocalの値を削除します。(:説明の便宜のために別々には必要なときに、それはすべてのコードクラスファイルに送信されます、PSを使用して実装しました)
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* \* Created with IntelliJ IDEA.
* \* @author: zuzi
* \* Date: 2019-06-11
* \* Time: 下午12:06
* \* Description:
* \
*/
@Slf4j
@SpringBootApplication
public class JavaStudyApplication implements WebMvcConfigurer {
public static void main(String[] args) {
SpringApplication.run(JavaStudyApplication.class, args);
}
public static final ThreadLocal threadLocal = new ThreadLocal<>();
@RestController("thread-local")
class ThreadLocalController {
@PostMapping
public String threadLocalSet() {
threadLocal.set("controller set");
return "设置成功!";
}
@GetMapping
public String threadLocalGet() {
return "获取到的threadLocal:为" + threadLocal.get();
}
}
class HttpFilter implements Filter {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) servletRequest;
log.info("do filter {} {} {}", Thread.currentThread().getId(), request.getServletPath(), threadLocal.get());
filterChain.doFilter(request, servletResponse);
}
}
class HttpInterceptor extends HandlerInterceptorAdapter {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
threadLocal.set("interceptor set");
log.info("pre handle , threadLocal:" + threadLocal.get());
return true;
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
log.info("after completion, threadLocal:" + threadLocal.get());
threadLocal.remove();
}
}
@Bean
public FilterRegistrationBean httpFilter() {
FilterRegistrationBean registrationBean = new FilterRegistrationBean<>();
registrationBean.setFilter(new HttpFilter());
registrationBean.addUrlPatterns("/thread-local/*");
return registrationBean;
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new HttpInterceptor()).addPathPatterns("/**");
}
}
复制代码
結果は
要求された場合GET /thread-local
の印刷結果ThreadLocalのフィルタは、nullに設定インターセプターThreadLocalの前に設定するので、印刷インターセプタ設定されていないため、またコントローラ、戻り値SETインターセプタに設けられ、インターセプタは共感インターセプタセットです。
リクエスト:
ログイン:
要求された場合はPOST /thread-local
、次のように、同様の結果は以下の通りでした。
リクエスト:
ログイン:
ロックすることにより
複数のスレッドに同期オブジェクトの共有プロパティを使用する場合、参照してください:のJavaマルチスレッド-ロック機構