spring4的@configure

阅读更多

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);

            }

        }

    }

 

}

 

三.三种测试方法

 

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!

 

你可能感兴趣的:(spring)