Spring4的@configure
1,生成自定义的bean,纳入spring管理
2,覆盖默认的同名bean
3,对于集成抽象类或实现接口的,这个实现类就是代替默认抽象类或接口
下面以异步线程为例:
本文记录@Async的基本使用以及通过实现ThreadFactory来实现对线程的命名。
@Async的基本使用
业务场景需要进行批量更新,已有数据id主键、更新的状态。单条更新性能太慢,所以使用in进行批量更新。但是会导致锁表使得其他业务无法访问该表,in的量级太低又导致性能太慢。
龙道友提出了一个解决方案,把要处理的数据分成几个list之后使用多线程进行数据更新。提到多线程可直接使用@Async注解来进行异步操作。
好的,接下来上面的问题我们不予解答,来说下@Async的简单使用
@Async在SpringBoot中的使用较为简单,所在位置如下:
一.启动类加入注解@EnableAsync
第一步就是在启动类中加入@EnableAsync注解 启动类代码如下:
@SpringBootApplication
@EnableAsync//可以写在具体配置类上
public class EurekaApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaApplication.class, args);
}
}
二.编写MyAsyncConfigurer类
MyAsyncConfigurer类实现了AsyncConfigurer接口,重写AsyncConfigurer接口的两个重要方法:
1.getAsyncExecutor:自定义线程池,若不重写会使用默认的线程池。
2.getAsyncUncaughtExceptionHandler:捕捉IllegalArgumentException异常.
一方法很好理解。二方法中提到的IllegalArgumentException异常在之后会说明。代码如下:
/**
* @author hsw
* @Date 20:12 2018/8/23
*/
@Slf4j
@Component
public class MyAsyncConfigurer implements AsyncConfigurer {
@Override
public Executor getAsyncExecutor() {
//定义一个最大为10个线程数量的线程池
ExecutorService service = Executors.newFixedThreadPool(10);
return service;
}
@Override
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
return new MyAsyncExceptionHandler();
}
class MyAsyncExceptionHandler implements AsyncUncaughtExceptionHandler {
@Override
public void handleUncaughtException(Throwable throwable, Method method, Object... objects) {
log.info("Exception message - " + throwable.getMessage());
log.info("Method name - " + method.getName());
for (Object param : objects) {
log.info("Parameter value - " + param);
}
}
}
}</code>
三.三种测试方法
1.无参无返回值方法
2.有参无返回值方法
3.有参有返回值方法
具体代码如下:
/**
* @author hsw
* @Date 20:07 2018/8/23
*/
@Slf4j
@Component
public class AsyncExceptionDemo {
@Async
public void simple() {
log.info("this is a void method");
}
@Async
public void inputDemo (String s) {
log.info("this is a input method,{}",s);
throw new IllegalArgumentException("inputError");
}
@Async
public Future hardDemo (String s) {
log.info("this is a hard method,{}",s);
Future future;
try {
Thread.sleep(3000);
throw new IllegalArgumentException();
}catch (InterruptedException e){
future = new AsyncResult("InterruptedException error");
}catch (IllegalArgumentException e){
future = new AsyncResult("i am throw IllegalArgumentException error");
}
return future;
}
}
在第二种方法中,抛出了一种名为IllegalArgumentException的异常,在上述第二步中,我们已经通过重写getAsyncUncaughtExceptionHandler方法,完成了对产生该异常时的处理。在处理方法中我们简单列出了异常的各个信息。ok,现在该做的准备工作都已完成,加个测试方法看看结果如何
/**
* @author hsw
* @Date 20:16 2018/8/23
*/
@RunWith(SpringRunner.class)
@SpringBootTest
@Slf4j
public class AsyncExceptionDemoTest {
@Autowired
private AsyncExceptionDemo asyncExceptionDemo;
@Test
public void simple() {
for (int i=0;i<3;i++){
try {
asyncExceptionDemo.simple();
asyncExceptionDemo.inputDemo("input");
Future future = asyncExceptionDemo.hardDemo("hard");
log.info(future.get());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
}
}
测试结果如下:
2018-08-25 16:25:03.856 INFO 4396 --- [ main] c.hsw.test.async.AsyncExceptionDemoTest : Started AsyncExceptionDemoTest in 3.315 seconds (JVM running for 4.184)
2018-08-25 16:25:03.947 INFO 4396 --- [pool-1-thread-1] com.hsw.test.async.AsyncExceptionDemo : this is a void method
2018-08-25 16:25:03.947 INFO 4396 --- [pool-1-thread-3] com.hsw.test.async.AsyncExceptionDemo : this is a hard method,hard
2018-08-25 16:25:03.947 INFO 4396 --- [pool-1-thread-2] com.hsw.test.async.AsyncExceptionDemo : this is a input method,input
2018-08-25 16:25:03.947 INFO 4396 --- [pool-1-thread-2] com.hsw.test.async.MyAsyncConfigurer : Exception message - inputError
2018-08-25 16:25:03.947 INFO 4396 --- [pool-1-thread-2] com.hsw.test.async.MyAsyncConfigurer : Method name - inputDemo
2018-08-25 16:25:03.947 INFO 4396 --- [pool-1-thread-2] com.hsw.test.async.MyAsyncConfigurer : Parameter value - input
2018-08-25 16:25:06.947 INFO 4396 --- [ main] c.hsw.test.async.AsyncExceptionDemoTest : i am throw IllegalArgumentException error
2018-08-25 16:25:06.948 INFO 4396 --- [pool-1-thread-4] com.hsw.test.async.AsyncExceptionDemo : this is a void method
2018-08-25 16:25:06.948 INFO 4396 --- [pool-1-thread-6] com.hsw.test.async.AsyncExceptionDemo : this is a hard method,hard
2018-08-25 16:25:06.948 INFO 4396 --- [pool-1-thread-5] com.hsw.test.async.AsyncExceptionDemo : this is a input method,input
2018-08-25 16:25:06.948 INFO 4396 --- [pool-1-thread-5] com.hsw.test.async.MyAsyncConfigurer : Exception message - inputError
2018-08-25 16:25:06.948 INFO 4396 --- [pool-1-thread-5] com.hsw.test.async.MyAsyncConfigurer : Method name - inputDemo
2018-08-25 16:25:06.948 INFO 4396 --- [pool-1-thread-5] com.hsw.test.async.MyAsyncConfigurer : Parameter value - input
2018-08-25 16:25:09.949 INFO 4396 --- [ main] c.hsw.test.async.AsyncExceptionDemoTest : i am throw IllegalArgumentException error
2018-08-25 16:25:09.950 INFO 4396 --- [pool-1-thread-7] com.hsw.test.async.AsyncExceptionDemo : this is a void method
2018-08-25 16:25:09.950 INFO 4396 --- [pool-1-thread-8] com.hsw.test.async.AsyncExceptionDemo : this is a input method,input
2018-08-25 16:25:09.950 INFO 4396 --- [pool-1-thread-8] com.hsw.test.async.MyAsyncConfigurer : Exception message - inputError
2018-08-25 16:25:09.950 INFO 4396 --- [pool-1-thread-9] com.hsw.test.async.AsyncExceptionDemo : this is a hard method,hard
2018-08-25 16:25:09.950 INFO 4396 --- [pool-1-thread-8] com.hsw.test.async.MyAsyncConfigurer : Method name - inputDemo
2018-08-25 16:25:09.950 INFO 4396 --- [pool-1-thread-8] com.hsw.test.async.MyAsyncConfigurer : Parameter value - input
2018-08-25 16:25:12.950 INFO 4396 --- [ main] c.hsw.test.async.AsyncExceptionDemoTest : i am throw IllegalArgumentException error
2018-08-25 16:25:12.953 INFO 4396 --- [ Thread-2] o.s.w.c.s.GenericWebApplicationContext : Closing org.springframework.web.context.support.GenericWebApplicationContext@71075444: startup date [Sat Aug 25 16:25:01 CST 2018]; root of context hierarchy
测试成功。
到此为止,关于@Async注解的基本使用内容结束。但是在测试过程中,我注意到线程名的命名为默认的pool-1-thread-X,虽然可以分辨出不同的线程在进行作业,但依然很不方便,为什么默认会以这个命名方式进行命名呢?
线程池的命名
点进Executors.newFixedThreadPool,发现在初始化线程池的时候有另一种方法
public static ExecutorService newFixedThreadPool(int nThreads, ThreadFactory threadFactory)
那么这个ThreadFactory为何方神圣?继续ctrl往里点,在类中发现这么一个实现类。
破案了破案了。原来是在这里对线程池进行了命名。那我们只需自己实现ThreadFactory接口,对命名方法进行重写即可,完成代码如下:
static class MyNamedThreadFactory implements ThreadFactory {
private static final AtomicInteger poolNumber = new AtomicInteger(1);
private final ThreadGroup group;
private final AtomicInteger threadNumber = new AtomicInteger(1);
private final String namePrefix;
MyNamedThreadFactory(String name) {
SecurityManager s = System.getSecurityManager();
group = (s != null) ? s.getThreadGroup() : Thread.currentThread().getThreadGroup();
if (null == name || name.isEmpty()) {
name = "pool";
}
namePrefix = name + "-" + poolNumber.getAndIncrement() + "-thread-";
}
public Thread newThread(Runnable r) {
Thread t = new Thread(group, r, namePrefix + threadNumber.getAndIncrement(), 0);
if (t.isDaemon())
t.setDaemon(false);
if (t.getPriority() != Thread.NORM_PRIORITY)
t.setPriority(Thread.NORM_PRIORITY);
return t;
}
}
然后在创建线程池的时候加上新写的类即可对线程名进行自定义。
@Override
public Executor getAsyncExecutor() {
ExecutorService service = Executors.newFixedThreadPool(10,new MyNamedThreadFactory("HSW"));
return service;
}
看看重命名后的执行结果。
2018-08-25 16:42:44.068 INFO 46028 --- [ main] c.hsw.test.async.AsyncExceptionDemoTest : Started AsyncExceptionDemoTest in 3.038 seconds (JVM running for 3.83)
2018-08-25 16:42:44.155 INFO 46028 --- [ HSW-1-thread-3] com.hsw.test.async.AsyncExceptionDemo : this is a hard method,hard
2018-08-25 16:42:44.155 INFO 46028 --- [ HSW-1-thread-2] com.hsw.test.async.AsyncExceptionDemo : this is a input method,input
2018-08-25 16:42:44.155 INFO 46028 --- [ HSW-1-thread-1] com.hsw.test.async.AsyncExceptionDemo : this is a void method
2018-08-25 16:42:44.155 INFO 46028 --- [ HSW-1-thread-2] com.hsw.test.async.MyAsyncConfigurer : Exception message - inputError
2018-08-25 16:42:44.155 INFO 46028 --- [ HSW-1-thread-2] com.hsw.test.async.MyAsyncConfigurer : Method name - inputDemo
2018-08-25 16:42:44.155 INFO 46028 --- [ HSW-1-thread-2] com.hsw.test.async.MyAsyncConfigurer : Parameter value - input
2018-08-25 16:42:47.155 INFO 46028 --- [ main] c.hsw.test.async.AsyncExceptionDemoTest : i am throw IllegalArgumentException error
2018-08-25 16:42:47.156 INFO 46028 --- [ HSW-1-thread-4] com.hsw.test.async.AsyncExceptionDemo : this is a void method
2018-08-25 16:42:47.156 INFO 46028 --- [ HSW-1-thread-5] com.hsw.test.async.AsyncExceptionDemo : this is a input method,input
2018-08-25 16:42:47.156 INFO 46028 --- [ HSW-1-thread-6] com.hsw.test.async.AsyncExceptionDemo : this is a hard method,hard
2018-08-25 16:42:47.156 INFO 46028 --- [ HSW-1-thread-5] com.hsw.test.async.MyAsyncConfigurer : Exception message - inputError
2018-08-25 16:42:47.156 INFO 46028 --- [ HSW-1-thread-5] com.hsw.test.async.MyAsyncConfigurer : Method name - inputDemo
2018-08-25 16:42:47.156 INFO 46028 --- [ HSW-1-thread-5] com.hsw.test.async.MyAsyncConfigurer : Parameter value - input
2018-08-25 16:42:50.156 INFO 46028 --- [ main] c.hsw.test.async.AsyncExceptionDemoTest : i am throw IllegalArgumentException error
2018-08-25 16:42:50.157 INFO 46028 --- [ HSW-1-thread-7] com.hsw.test.async.AsyncExceptionDemo : this is a void method
2018-08-25 16:42:50.157 INFO 46028 --- [ HSW-1-thread-8] com.hsw.test.async.AsyncExceptionDemo : this is a input method,input
2018-08-25 16:42:50.157 INFO 46028 --- [ HSW-1-thread-9] com.hsw.test.async.AsyncExceptionDemo : this is a hard method,hard
2018-08-25 16:42:50.157 INFO 46028 --- [ HSW-1-thread-8] com.hsw.test.async.MyAsyncConfigurer : Exception message - inputError
2018-08-25 16:42:50.157 INFO 46028 --- [ HSW-1-thread-8] com.hsw.test.async.MyAsyncConfigurer : Method name - inputDemo
2018-08-25 16:42:50.157 INFO 46028 --- [ HSW-1-thread-8] com.hsw.test.async.MyAsyncConfigurer : Parameter value - input
2018-08-25 16:42:53.157 INFO 46028 --- [ main] c.hsw.test.async.AsyncExceptionDemoTest : i am throw IllegalArgumentException error
2018-08-25 16:42:53.161 INFO 46028 --- [ Thread-2] o.s.w.c.s.GenericWebApplicationContext : Closing org.springframework.web.context.support.GenericWebApplicationContext@71075444: startup date [Sat Aug 25 16:42:41 CST 2018]; root of context hierarchy
NICE!
相关推荐
在本文中,我们将深入探讨如何将Spring4框架与Jersey2.9进行集成,以便创建一个功能丰富的RESTful Web服务。这个入门案例采用Maven作为项目构建工具,使得整个过程更加简便。 首先,理解Spring4和Jersey2.9的核心...
4. **其他解决方案**: - 如果你使用的是Thymeleaf等模板引擎,它们通常会自动转义输出内容,防止XSS攻击。 - 如果你希望在前端处理转义,可以在JavaScript中使用`encodeURI()`或`encodeURIComponent()`函数,但这...
### Spring Boot 1.5.2、Spring Security 4 与 Spring Data JPA 整合实践 #### 一、项目背景及目标 本项目旨在通过一个具体的案例来演示如何将 Spring Boot 1.5.2、Spring Security 4 以及 Spring Data JPA 进行...
Spring4安全框架是基于Spring Framework 4.x版本的Spring Security模块,它是一个强大的安全管理组件,用于保护基于Java的Web应用程序。Maven是一个流行的项目管理和综合工具,它通过管理项目的依赖关系,帮助开发者...
PropertyConfigurator.configure("classpath:log4j.properties"); ``` 3. **在代码中使用**:Spring自动注入`Logger`实例,可以直接在代码中调用方法记录日志: ```java @Autowired private Logger logger; ...
Spring Boot学习笔记-------(三)spring boot配置的配套代码,博客地址:https://blog.csdn.net/huaya1127/article/details/104152567
在Spring应用中,我们可以通过`PropertyConfigurator.configure()`方法加载Log4J配置,或者在Spring的`context.xml`中使用`ContextLoaderListener`来自动加载。例如: ```xml <listener-class>org.spring...
usually multiple ways to configure the application. Although it is a good thing to have multiple options, it can be overwhelming to the beginners. Spring Boot addresses this “Spring applications need...
Spring Boot 与 Spring Security 4 最新整合实例 Spring Boot 和 Spring Security 4 最新整合实例是一篇详细的教程,旨在指导用户如何使用 Spring Boot 和 Spring Security 4 实现用户身份认证、登录退出、用户...
Spring Boot 和 Spring Security 整合实例详解 Spring Boot 是一个快速开发框架,它简化了 Spring 应用的初始搭建以及开发过程。而 Spring Security 是一个强大的安全框架,用于处理身份认证(Authentication)和...
Spring Boot集成Spring Security是开发基于Java的Web应用时常见的安全框架选择。Spring Security提供了一整套强大且灵活的安全控制机制,使得开发者可以轻松地实现身份验证、授权以及各种安全功能。下面将详细介绍...
在Spring Security 4中,我们可以通过自定义过滤器来扩展其功能,以满足特定的安全需求。在这个小例子中,我们将探讨如何创建并集成自定义过滤器,以及它在Spring Security中的工作原理。 首先,我们需要理解Spring...
4. **SpringSecurity认证流程** - 用户提交登录请求,请求被SpringSecurity的过滤器拦截。 - 认证过滤器(如`UsernamePasswordAuthenticationFilter`)提取用户名和密码,并调用`UserDetailsService`进行验证。 -...
Spring Security 是一个强大的安全框架,用于为Java应用提供身份验证和授权服务。在这个完整的项目实例中,我们将深入探讨Spring Security的核心概念以及如何将其应用于实际的Web应用程序开发。 首先,我们从用户、...
4. **安全认证的进一步定制**: - 如果需要更复杂的认证策略,比如OAuth2或其他JWT令牌验证,可以通过自定义`Filter`或使用Spring Security提供的扩展点来实现。 - 可以添加额外的过滤器,例如: ```java @...
Configure and use Spring Boot Use non-functional requirements with Spring Boot Actuator Carry out web development with Spring Boot Persistence with JDBC, JPA and NoSQL Databases Messaging with JMS, ...
总之,Spring Boot和Spring Security 4的整合为开发者提供了一个高效且灵活的安全框架,帮助我们快速构建安全可控的应用程序。通过深入学习和实践,开发者可以熟练掌握这一重要技能,提升自己的专业能力。
4. **Web安全配置** Spring Security的配置通常在Java配置类中完成,通过`WebSecurityConfigurerAdapter`的子类实现。例如,配置认证和授权规则,以及自定义登录页面: ```java @Configuration @...
### Spring Security 4 登录示例详解 #### 一、概览 在现代Web应用开发中,安全性至关重要。Spring Security 是一款广泛使用的安全框架,它为基于Spring的应用提供了全面的安全解决方案,包括认证、授权等核心功能...
4. Working with Spring Boot 5. Learning about Spring Boot Features 6. Moving to Production 7. Advanced Topics II. Getting Started 8. Introducing Spring Boot 9. System Requirements 9.1. Servlet ...