Spring AOP异步操作实现及Cache操作实现(PROJECT04_DAY03_01)

5. Spring AOP异步操作实现

5.1 异步场景分析

在开发系统的过程中,通常会考虑到系统的性能问题,提升系统性能的一个重要思想就是“串行”改“并行”。说起“并行”自然离不开“异步”,今天我们就来聊聊如何使用Spring的@Async的异步注解。

5.2 Spring 业务的异步实现

5.2.1 启动异步配置

在基于注解方式的配置中,借助@EnableAsync注解进行异步启动声明,Spring Boot版的项目中,将@EnableAsync注解应用到启动类上,代码示例如下:

   @EnableAsync //Spring容器启动时会创建线程池
   @SpringBootApplication
   public class Application {
        public static void main(String[] args) {
                SpringApplication.run(Application.class, args);
        }
}

5.2.2 Spring中@Async注解应用

在需要异步执行的业务方法上,使用@Async方法进行异步声明。

@Async
@Transactional(propagation = Propagation.REQUIRES_NEW)
@Override
public void saveObject(SysLog entity) {
  System.out.println("SysLogServiceImpl.save:"+Thread.currentThread().getName());
  sysLogDao.insertObject(entity);
  //try{Thread.sleep(5000);}catch(Exception e) {}
}

当我们需要自己对Spring框架提供的线程池进行一些简易配置,可以参考如下代码:

spring:
  task:
    execution:
      pool:
        queue-capacity: 128
        core-size: 5
        max-size: 128
        keep-alive: 60000
      thread-name-prefix: db-service-task-

对于Spring框架中线程池配置参数的涵义,可以参考ThreadPoolExecutor对象中的解释。

说明:对于@Async注解默认会基于ThreadPoolTaskExecutor对象获取工作线程,然后调用由@Async描述的方法,让方法运行于另一个工作线程,以实现异步操作。但是假如系统中的默认拒绝处理策略,任务执行过程的异常处理不能满足我们自身业务需求的话,我可以对异步线程池进行自定义.(SpringBoot中默认的异步配置可以参考自动配置对象TaskExecutionAutoConfiguration).

5.2.3 Spring 自定义异步池的实现(拓展)

为了让Spring中的异步池更好的服务于我们的业务,可以自定义线程池优化设计如下:关键代码如下:

package com.cy.pj.common.annotation;
@Slf4j
@Setter
@Configuration //此注解描述的类为一个配置类,需要交给 Spring 管理
@ConfigurationProperties("spring.async.task")//读取 Spring 配置文件中以 spring.async.task 为前缀的数据,并通过 set 方法注入给属性
public class SpringAsyncConfig implements AsyncConfigurer {
	private int corePoolSize = 5;
	private int maxPoolSize = 100;
	private int keepAliveSeconds = 60;
	private int queueCapacity=  128;
	private String threadNamePrefix = "tast===>";
	@Override
	public Executor getAsyncExecutor() {
		System.out.println("corePoolSize="+corePoolSize);
		ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
		executor.setCorePoolSize(corePoolSize);
		executor.setMaxPoolSize(maxPoolSize);
		executor.setKeepAliveSeconds(keepAliveSeconds);
		executor.setQueueCapacity(queueCapacity);
		executor.setThreadNamePrefix(threadNamePrefix);
		//自定义拒绝处理策略
		executor.setRejectedExecutionHandler(new RejectedExecutionHandler() {
			@Override
			public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
				log.error("队列已满并且已无线程可用");
			}
		});
		executor.initialize();
		return executor;
	}
	@Override
	public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
		return new AsyncUncaughtExceptionHandler() {
			@Override
			public void handleUncaughtException(Throwable ex, Method method, Object... params) {
				log.error("任务执行时出现了 {}",ex.getMessage());
			}
		};
	}
}

其中:@ConfigurationProperties(“async-thread-pool”)的含义是读取application.yml配置文件中以"spring.async.task"名为前缀的配置信息,并通过所描述类的set方法赋值给对应的属性,在application.yml中连接池的关键配置如下:

spring:
	async:
   		task:
      		corePoolSize: 10
      		maxPoolSize: 20
      		keepAliveSeconds: 50
      		queueCapacity: 128
      		threadNamePrefix: db-async-service-task-

后续在业务类中,假如我们使用@Async注解描述业务方法,默认会使用ThreadPoolTaskExecutor池对象中的线程执行异步任务。

6. Spring AOP中Cache操作实现(拓展)

6.1 缓存场景分析

在业务方法中我们可能调用数据层方法获取数据库中数据,假如访问数据的频率比较为高,为了提高的查询效率,降低数据库的访问压力,可以在业务层对数据进行缓存.

6.2 Spring 中业务缓存应用实现

6.2.1 启动缓存配置

在项目(SpringBoot项目)的启动类上添加@EnableCaching注解,以启动缓存配置。关键代码如下:

package com.cy;
/**
 * @EnableCaching 注解表示启动缓存配置
 */
@EnableCaching
@SpringBootApplication
public class Application {
  public static void main(String[] args) {
    SpringApplication.run(Application.class, args);
  }
}

6.2.2 业务方法上应用缓存配置

在需要进行缓存的业务方法上通过@Cacheable注解对方法进行相关描述.表示方法的返回值要存储到Cache中,假如在更新操作时需要将cache中的数据移除,可以在更新方法上使用@CacheEvict注解对方法进行描述。例如:

第一步:在相关模块查询相关业务方法中,使用缓存,关键代码如下:

@Cacheable(value = "deptCache")
@Transactional(readOnly = true)
public List<Map<String,Object>> findObjects() {
....
}

其中,value属性的值表示要使用的缓存对象,名字自己指定,其中底层为一个map对象,当向cache中添加数据时,key默认为方法实际参数的组合。

第二步:在相关模块更新时,清除指定缓存数据,关键代码如下:

@CacheEvict(value="deptCache",allEntries=true)
@Override
public int saveObject(SysDept entity) {...}

其中,allEntries表示清除所有。

说明:spring中的缓存应用原理,如图-15所示:
在这里插入图片描述
图-15

6.2.3 Spring中自定义缓存的实现(拓展)

在Spring中默认cache底层实现是一个Map对象,假如此map对象不能满足我们实际需要,在实际项目中我们可以将数据存储到第三方缓存系统中.

7. 总结

7.1 重难点分析

AOP 是什么,解决了什么问题,实现原理,应用场景。
AOP 编程基本步骤及实现过程(以基于AspectJ框架实现为例)。
AOP 编程中的核心对象及应用关系。
AOP 思想在Spring中的实现原理分析。
AOP 编程中基于注解注解方式的配置实现。
AOP 编程中基于注解方式的事务控制。
AOP 编程中异步操作的实现?
AOP 编程中的缓存应用?

7.2 FAQ分析

什么是OCP原则(开闭原则)?
什么是DIP原则 (依赖倒置)?
什么是单一职责原则(SRP)?
Spring 中AOP的有哪些配置方式?(XML,注解)
Spring 中AOP 的通知有哪些基本类型?(5种)
Spring 中AOP是如何为Bean对象创建代理对象的?(JDK,CGLIB)
Spring 中AOP切面的执行顺序如何指定?(@Order)
Spring 单体架构项目中事务的控制要通过Connection对象实现,?
Spring 如何保证一个线程一个Connection对象?借助ThreadLocal实现.?
多个事务并发执行时可能会出现什么问题?
如何理解数据库中的的悲观锁和乐观锁?
你了解事务的隔离级别吗?知道具体的应用场景吗?
……
….

7.3 Bug分析

切入点应用错误,如图-17所示:
在这里插入图片描述
图-17

问题分析:检查切入点的引入是否丢掉了"()".

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
可以使用Spring AOP的Aspect注解来实现操作记录到数据库的功能。首先,需要创建一个切面类,使用@Aspect注解进行标记,并在该类中声明一个@Before注解的方法。在该方法中,使用JoinPoint对象来获取连接点信息,进而获取操作记录的相关信息,并将其保存到数据库中。需要注意的是,操作记录的相关信息应该尽可能地详细,包括操作人员、操作时间、操作类型、操作目标等。 示例代码如下: @Aspect @Component public class OperatorAspect { @Autowired private OperatorLogService operatorLogService; @Before("execution(* com.example.demo.service.*.*(..))") public void logOperator(JoinPoint joinPoint) { OperatorLog operatorLog = new OperatorLog(); operatorLog.setOperatorName("Admin"); operatorLog.setOperatorTime(LocalDateTime.now()); operatorLog.setOperatorType("Update"); operatorLog.setOperatorTarget(joinPoint.getSignature().toShortString()); operatorLogService.save(operatorLog); } } 其中,JoinPoint对象提供了获取连接点信息的多种方法,如下表所示: 方法名 描述 getArgs() 获取连接点方法运行时的参数列表 getThis() 获取代理对象 getTarget() 获取目标对象 getSignature() 获取连接点的方法签名对象 toShortString() 获取连接点的方法简短签名名称 toLongString() 获取连接点的方法全限定签名名称 getKind() 获取连接点类型,如method-execution getSourceLocation() 获取连接点所在的位置 getStaticPart() 获取连接点所在的静态部分 需要在Spring配置文件中将该切面类注入到容器中,并启用AOP自动代理: <context:component-scan base-package="com.example.demo"/> <aop:aspectj-autoproxy proxy-target-class="true"/>

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值