前言:Spring的Aop称为面向切面编程,在开发系统主要用于日志、事物、权限等。
基本概念:
1.@Aspect(切面):切面类,伴随@Component里面可以定义切入点和通知
2.@JoinPoint(链接点):一般是包含切点标记方法的掉用的返回值、参数、切点中标记的内容
3.Advice(通知):Aop在特定切入点上执行的增强处理,有before,after,afterReturning,afterThrowing,around
4.@Pointcut(切入点):带有注解的切点
5.AOP代理:AOP框架的对象,代理就是目标对象的加强。Spring中的AOP代理可以使用JDK动态代理,也可以是CGLIB代理,前者基于接口,后者基于子类
上代码演示:场景为实先对用户信息的操作日志的记录
一:先定义切点注解(后面把它放在要标记的方法位置,去切这个方法也就是这个方法执行前我要咋样后我要咋样。。。。。)
//切点主注解
@Target({ElementType.PARAMETER,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Log {
/*模块*/
public String title() default "";
/*功能*/
public BusinessType businessType() default BusinessType.OTHER;
/*是否需要保存请求的参数*/
public boolean isSaveRequesDate() default true;
}
二:这是用户的删除和修改操作的接口(这里随便)我们用户自己定义的注解去切它一下(简单的增删改查我就不说了,自己去建个表吧)
@RestController
@RequestMapping("/user")
public class TbUserController{
@Resource
private TbUserService tbUserService;
//这是用户删除操作,删除之后我要记录一个这个id的用户删掉了
@Log(businessType = BusinessType.DELETE,title = "用户")
@DeleteMapping("/removeUser")
public AjaxResult removeUser(Integer id){
try {
tbUserService.removeUser(id);
return AjaxResult.success("删除用户成功");
} catch (Exception e) {
return AjaxResult.error("删除用户失败");
}
}
//这是用户的修改操作,修改值我要记录一下这个id的用户修改了
@Log(businessType = BusinessType.UPDATE,title = "用户")
@PostMapping("/editUser")
public AjaxResult editUser(@RequestBody TbUser tbUser){
try {
tbUserService.editUser(tbUser);
return AjaxResult.success("修改成功");
} catch (Exception e) {
return AjaxResult.error("修改失败");
}
}
}
三:定义一下切面类(它主要是获取一下切点也就是切点标记的方法执行了就会把的参数、方法的返回值传到这里来执行前写一下逻辑代码执行之后在干嘛干嘛。。)
@Aspect
@Component
public class LogAspect {
//配置切入点
@Pointcut("@annotation(com.example.demo.config.Log)")
public void logPointCut(){
}
/**
* 处理完请求后执行
* @param joinPoint 切点
* @param jsonResult
*/
@AfterReturning(pointcut = "logPointCut()",returning = "jsonResult")
public void doAfterReturning(JoinPoint joinPoint,Object jsonResult){
handleLog(joinPoint,null,jsonResult);
}
@AfterThrowing(pointcut = "logPointCut()",throwing = "e")
public void doAfterThrowing(JoinPoint joinPoint,Exception e){
handleLog(joinPoint,e,null);
}
protected void handleLog(final JoinPoint joinPoint,final Exception e,Object jsonResult){
// 获得注解
try {
Log controllerLog = getAnnotationLog(joinPoint);
if (controllerLog.title().equals("用户")){
//修改保存
if (controllerLog.businessType().equals(BusinessType.UPDATE)){
TbUser tbUser=(TbUser)joinPoint.getArgs()[0];
TbUserOperationLog tbUserOperationLog=new TbUserOperationLog();
tbUserOperationLog.setUserId(tbUser.getId());
tbUserOperationLog.setOperation(controllerLog.businessType().name());
//这是一个线程池的提交任务的方法用来定时交接要保存的信息
AsyncManager.me().execute(AsyncFactory.userLog(tbUserOperationLog));
}
//删除保存
if (controllerLog.businessType().equals(BusinessType.DELETE)){
Integer userId=(Integer) joinPoint.getArgs()[0];
TbUserOperationLog tbUserOperationLog=new TbUserOperationLog();
tbUserOperationLog.setUserId(userId);
tbUserOperationLog.setOperation(controllerLog.businessType().name());
//这是一个线程池的提交任务的方法用来定时交接要保存的信息
AsyncManager.me().execute(AsyncFactory.userLog(tbUserOperationLog));
}
}
} catch (Exception e1) {
e1.printStackTrace();
}
}
/**
* 是否存在注解,如果存在就获取
*/
private Log getAnnotationLog(JoinPoint joinPoint) throws Exception
{
Signature signature = joinPoint.getSignature();
MethodSignature methodSignature = (MethodSignature) signature;
Method method = methodSignature.getMethod();
if (method != null)
{
return method.getAnnotation(Log.class);
}
return null;
}
}
下面附上线程池提交定时任务的方法与这个aop无关的
public class Threads {
private static final Logger logger = LoggerFactory.getLogger(Threads.class);
/**
* sleep等待,单位为毫秒
*/
public static void sleep(long milliseconds)
{
try
{
Thread.sleep(milliseconds);
}
catch (InterruptedException e)
{
return;
}
}
/**
* 停止线程池
* 先使用shutdown, 停止接收新任务并尝试完成所有已存在任务.
* 如果超时, 则调用shutdownNow, 取消在workQueue中Pending的任务,并中断所有阻塞函数.
* 如果仍人超時,則強制退出.
* 另对在shutdown时线程本身被调用中断做了处理.
*/
public static void shutdownAndAwaitTermination(ExecutorService pool)
{
if (pool != null && !pool.isShutdown())
{
pool.shutdown();
try
{
if (!pool.awaitTermination(120, TimeUnit.SECONDS))
{
pool.shutdownNow();
if (!pool.awaitTermination(120, TimeUnit.SECONDS))
{
logger.info("Pool did not terminate");
}
}
}
catch (InterruptedException ie)
{
pool.shutdownNow();
Thread.currentThread().interrupt();
}
}
}
/**
* 打印线程异常信息
*/
public static void printException(Runnable r, Throwable t)
{
if (t == null && r instanceof Future<?>)
{
try
{
Future<?> future = (Future<?>) r;
if (future.isDone())
{
future.get();
}
}
catch (CancellationException ce)
{
t = ce;
}
catch (ExecutionException ee)
{
t = ee.getCause();
}
catch (InterruptedException ie)
{
Thread.currentThread().interrupt();
}
}
if (t != null)
{
logger.error(t.getMessage(), t);
}
}
}
/*线程池配置类*/
@Configuration
public class ThreadPoolConfig {
// 线程池基本大小
private int corePoolSize = 50;
// 最大可创建的线程数
private int maxPoolSize = 200;
// 队列最大长度
private int queueCapacity = 1000;
// 线程存活保持时间
private int keepAliveSeconds = 300;
@Bean(name = "threadPoolTaskExecutor")
public ThreadPoolTaskExecutor threadPoolTaskExecutor()
{
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setMaxPoolSize(maxPoolSize);
executor.setCorePoolSize(corePoolSize);
executor.setQueueCapacity(queueCapacity);
executor.setKeepAliveSeconds(keepAliveSeconds);
// 线程池对拒绝任务(无线程可用)的处理策略
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
return executor;
}
/**
* 执行周期性或定时任务
*/
@Bean(name = "scheduledExecutorService")
protected ScheduledExecutorService scheduledExecutorService()
{
return new ScheduledThreadPoolExecutor(corePoolSize,
new BasicThreadFactory.Builder().namingPattern("schedule-pool-%d").daemon(true).build())
{
@Override
protected void afterExecute(Runnable r, Throwable t)
{
super.afterExecute(r, t);
Threads.printException(r, t);
}
};
}
}
//线程池调用类
public class AsyncManager {
/**
* 操作延迟10毫秒
*/
private final int OPERATE_DELAY_TIME = 10;
/**
* 异步操作任务调度线程池
*/
private ScheduledExecutorService executor = SpringUtils.getBean("scheduledExecutorService");
/**
* 单例模式
*/
private AsyncManager(){}
private static AsyncManager me = new AsyncManager();
public static AsyncManager me()
{
return me;
}
/**
* 延迟执行任务
*
* @param task 任务
*/
public void execute(TimerTask task)
{
executor.schedule(task, OPERATE_DELAY_TIME, TimeUnit.MILLISECONDS);
}
/**
* 停止任务线程池
*/
public void shutdown()
{
Threads.shutdownAndAwaitTermination(executor);
}
}
//要提交到线程池中的任务
public class AsyncFactory {
public static TimerTask userLog(final TbUserOperationLog tbUserOperationLog){
return new TimerTask() {
@Override
public void run() {
//保存用户操作日志信息
SpringUtils.getBean(TbUserOperationLogService.class).addTbUserOperationLog(tbUserOperationLog);
}
};
}
public static TimerTask say(){
return new TimerTask() {
@Override
public void run() {
System.out.println("我是线程要做的事");
}
};
}
}
@Component
public final class SpringUtils implements BeanFactoryPostProcessor, ApplicationContextAware
{
/** Spring应用上下文环境 */
private static ConfigurableListableBeanFactory beanFactory;
private static ApplicationContext applicationContext;
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException
{
SpringUtils.beanFactory = beanFactory;
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException
{
SpringUtils.applicationContext = applicationContext;
}
/**
* 获取对象
*
* @param name
* @return Object 一个以所给名字注册的bean的实例
* @throws org.springframework.beans.BeansException
*
*/
@SuppressWarnings("unchecked")
public static <T> T getBean(String name) throws BeansException
{
return (T) beanFactory.getBean(name);
}
/**
* 获取类型为requiredType的对象
*
* @param clz
* @return
* @throws org.springframework.beans.BeansException
*
*/
public static <T> T getBean(Class<T> clz) throws BeansException
{
T result = (T) beanFactory.getBean(clz);
return result;
}
/**
* 如果BeanFactory包含一个与所给名称匹配的bean定义,则返回true
*
* @param name
* @return boolean
*/
public static boolean containsBean(String name)
{
return beanFactory.containsBean(name);
}
/**
* 判断以给定名字注册的bean定义是一个singleton还是一个prototype。 如果与给定名字相应的bean定义没有被找到,将会抛出一个异常(NoSuchBeanDefinitionException)
*
* @param name
* @return boolean
* @throws org.springframework.beans.factory.NoSuchBeanDefinitionException
*
*/
public static boolean isSingleton(String name) throws NoSuchBeanDefinitionException
{
return beanFactory.isSingleton(name);
}
/**
* @param name
* @return Class 注册对象的类型
* @throws org.springframework.beans.factory.NoSuchBeanDefinitionException
*
*/
public static Class<?> getType(String name) throws NoSuchBeanDefinitionException
{
return beanFactory.getType(name);
}
/**
* 如果给定的bean名字在bean定义中有别名,则返回这些别名
*
* @param name
* @return
* @throws org.springframework.beans.factory.NoSuchBeanDefinitionException
*
*/
public static String[] getAliases(String name) throws NoSuchBeanDefinitionException
{
return beanFactory.getAliases(name);
}
/**
* 获取aop代理对象
*
* @param invoker
* @return
*/
@SuppressWarnings("unchecked")
public static <T> T getAopProxy(T invoker)
{
return (T) AopContext.currentProxy();
}
/**
* 获取当前的环境配置,无配置返回null
*
* @return 当前的环境配置
*/
public static String[] getActiveProfiles()
{
return applicationContext.getEnvironment().getActiveProfiles();
}