spring-4.3.4.RELEASE集成AOP 实战

一、依赖引入 (包括 spring-aop 以及 aspectj)

 
     org.springframework
     spring-aop
     4.3.4.RELEASE
  
 
     org.aspectj
     aspectjweaver
     1.6.12
    

二、切面配置代码 (使用 javaConfig实现)

package com.weker.service.aspect;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;

/**
 * 启用AspectJ注解的自动代理
 *
 * Created by barnabas on  2018/4/10
 */
@Configuration
@EnableAspectJAutoProxy
@ComponentScan
public class aspectConfig {
    @Bean
    public RoomUserInfoAspect roomInfoAspect() {
        return new RoomUserInfoAspect();
    }
}

三、创建切面

package com.weker.service.aspect;

import com.weker.domain.model.CommunityResidentDo;
import com.weker.domain.model.CommunityRoomDo;
import com.weker.domain.param.CommunityResidentQueryParam;
import com.weker.service.common.RedisService;
import com.weker.service.community.CommunityResidentService;
import com.weker.service.community.CommunityRoomService;
import com.weker.service.model.CommunityResidentInfo;
import com.weker.service.model.RedisKeys;
import com.weker.service.model.TransmissionCmd;
import com.weker.service.model.UserBaseInfo;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;

/**
 * 用户房间信息切面
 *
 * Created by barnabas on  2018/4/10
 */
@Aspect
@Component
public class RoomUserInfoAspect {
    @Resource
    private CommunityRoomService communityRoomService;
    @Resource
    private CommunityResidentService communityResidentService;
    @Resource
    private RedisService redisService;

    //多线程异步执行
    private ExecutorService work = Executors.newSingleThreadExecutor(new ThreadFactory() {
        @Override
        public Thread newThread(Runnable r) {
            return new Thread(r, "ROOMUSERINFO-ASPECT");
        }
    });

   
    //添加住户(使用切点 userId)
    @Pointcut("execution(* com.weker.service.community.CommunityResidentService.addCommunityResidentInfo(..)) && args(userId)")
    public void PointCutAddResident(Long userId) {}
    
    //创建前置通知(通知方法会在目标方法调用之前执行)
    @Before(value = "PointCutAddResident(userId)")
    public void beforeAddResident(Long userId) {
        try {
            //方法开始前执行
            String hashName = RedisKeys.CacheHashName.ROOM_INFO.getKey();
            List roomIdList = getRoomIdListByUserId(userId);
            for (Long roomId : roomIdList) {
                redisService.delete(hashName, roomId+"");
            }
        } catch (Throwable e) {
            System.out.println(e.getMessage());
        }
    }
    
    //创建后置通知(通知方法会在目标方法返回后调用)
    @AfterReturning(value = "PointCutAddResident(userId)",returning ="roomId")
    public void afterReturningAddResident(Long roomId) {
        afterReturningResident(roomId);
    }

   //创建环绕通知
    @Around(value = "PointCutAddResident(userId)")
    public void aroundAddResident(ProceedingJoinPoint joinPoint,Long userId) {
        try {
            //方法开始前执行
            String hashName = RedisKeys.CacheHashName.ROOM_INFO.getKey();
            List roomIdList = getRoomIdListByUserId(userId);
            for (Long roomId : roomIdList) {
                redisService.delete(hashName, roomId+"");
            }
            //将控制权交给被通知的方法(一定需要)
            joinPoint.proceed();
            //方法结束后执行
            for (Long roomId : roomIdList) {
                afterReturningResident(roomId);
            }
        } catch (Throwable e) {
            System.out.println(e.getMessage());
        }
    }

    //根据用户id获取房间号Idlist
    private List getRoomIdListByUserId(Long userId) {
        List roomIdList = new ArrayList();
        CommunityResidentQueryParam param = new CommunityResidentQueryParam();
        param.setIsMoveout(2);
        param.setUserId(userId);
        List residentDoList =                      communityResidentService.getCommunityResidentListByParam(param);
        if (!CollectionUtils.isEmpty(residentDoList)) {
            for (CommunityResidentDo residentDo : residentDoList) {
                roomIdList.add(residentDo.getRoomnoId());
            }
        }

        return roomIdList;
    }

    //根据住户id获取房间号id
    private Long getRoomIdByResidentId(Long residentId) {
        Long roomId = 0L;
        CommunityResidentDo residentDo = communityResidentService.getCommunityResidentByPrimaryKey(residentId);
        if (null != residentDo) {
            roomId = residentDo.getRoomnoId();
        }

        return roomId;
    }

    //开辟新的线程执行aop 修改住户之后返回 (由于对应的方法需要处理的内容比较多,比较耗时,因此开辟一个新新的线程来执行对应的方法,方便对应的目标方法可以先返回)
    public void afterReturningResident(final Long roomId) {
        work.execute(new Runnable() {
            @Override
            public void run() {
                try {
                    communityRoomService.updateRoomInfoCacheByRoomId(roomId);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }
}

小结

这篇文章主要是讲述spring集成aop的实战,可以直接使用。因为spring集成aop执行通知方法完成之后才会返回给目标方法,因此增加了多线程内容,来实现目标方法接口的返回。文章里面包含@Before、@AfterReturning、@Around三种通知方式,在我们平时的aop使用中基本可以满足要求,如有错误,欢迎指教!

你可能感兴趣的:(spring-4.3.4.RELEASE集成AOP 实战)