美文网首页我爱编程
spring-4.3.4.RELEASE集成AOP 实战

spring-4.3.4.RELEASE集成AOP 实战

作者: Barnabas1 | 来源:发表于2018-04-11 14:58 被阅读0次

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

     <dependency>
         <groupId>org.springframework</groupId>
         <artifactId>spring-aop</artifactId>
         <version>4.3.4.RELEASE</version>
     </dependency> 
     <dependency>
         <groupId>org.aspectj</groupId>
         <artifactId>aspectjweaver</artifactId>
         <version>1.6.12</version>
     </dependency>   
    

    二、切面配置代码 (使用 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<Long> 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<Long> 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<Long> getRoomIdListByUserId(Long userId) {
            List<Long> roomIdList = new ArrayList<Long>();
            CommunityResidentQueryParam param = new CommunityResidentQueryParam();
            param.setIsMoveout(2);
            param.setUserId(userId);
            List<CommunityResidentDo> 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 实战

        本文链接:https://www.haomeiwen.com/subject/ltaahftx.html