关于aop对目标方法性能影响的一些记录

今天记录一下自己对aop的一个理解误区,实际上是给过去初入java的自己一个交代
数年之前我刚入坑java的时候,公司对日志的打印把控的比较严格,因为项目比较大,大量的日志经常会导致系统整体运行速度不能满足业务需求。

那么我的问题来了:logger不是说是使用aop实现的么,aop不是说完全不会影响原有程序的运行的么(所以永远都不要猜一个菜鸟心里在想什么),所以我问了一下当时我身边的大佬。他当时给我的回答是:日志打印虽然不会影响程序的运行,但是大量的日志输出会占用大量的io,从而拖慢系统运行速度,emmmm也不算错

目前暂时还没有研究logger的源代码,也不知道是否如网上所说是使用aop实现的,但是只是针对aop倒是可以试上一试,借用一下之前的代码java自定义注解并结合aop实现权限控制

package com.yinyuecheng.jioencryption.aop;

import com.google.gson.Gson;
import com.yinyuecheng.jioencryption.DiyIntegerface.RoleValid;
import com.yinyuecheng.jioencryption.common.RoleValidEnum;
import com.yinyuecheng.jioencryption.common.UserInfo;
import com.yinyuecheng.jioencryption.exception.AuthorityException;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpSession;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.concurrent.ConcurrentHashMap;

@Aspect
@Component
public class RoleValidAround {
    @Autowired
    HttpSession httpSession;

    private static Gson gson = new Gson();
    private Logger logger = LoggerFactory.getLogger(RoleValidAround.class);

    @Pointcut("@annotation(com.yinyuecheng.jioencryption.DiyIntegerface.RoleValid)")
    public void RoleValidAroundPointCut(){}

    @Around("RoleValidAroundPointCut()")
    public Object validAround(ProceedingJoinPoint joinPoint) throws IllegalAccessException, InstantiationException {
        //获取传入目标方法的参数
        Object[] args = joinPoint.getArgs();
        for (int i = 0; i < args.length; i++) {
            System.out.println("第" + (i+1) + "个参数为:" + args[i]);
        }
        System.out.println("被代理的对象:" + joinPoint.getTarget());
        System.out.println("代理对象自己:" + joinPoint.getThis());

        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
        Method method = methodSignature.getMethod();
        RoleValid roleValid = method.getAnnotation(RoleValid.class);
        RoleValidEnum limitPower = roleValid.role();
        //UserInfo userInfo = gson.fromJson(gson.toJson(httpSession.getAttribute("userInfo")),UserInfo.class);
        Object[] objs = joinPoint.getArgs();
        Class [] paramClasses = method.getParameterTypes();
        UserInfo userInfo = null;
        for(int i=0;i<paramClasses.length;i++){
            if(paramClasses[i].newInstance() instanceof UserInfo){
                userInfo = gson.fromJson(gson.toJson(objs[i]),UserInfo.class);
            }
        }
        if(userInfo==null){
            System.out.println("无可检索的权限信息,请检查入参是否规范");
            return null;
        }
        String user = userInfo.getPower();
        /*ConcurrentHashMap map = gson.fromJson(gson.toJson(objs[0]),ConcurrentHashMap.class);
        String user = (String)map.get("power");*/
        RoleValidEnum userPower = RoleValidEnum.getPower(user);
        logger.info("~~~~~~~~~~limitPower:{},~~~~~~~~~~~userPower:{}",limitPower,userPower);
       if(RoleValidEnum.hasPower(userPower,limitPower)){
            Object result = null ;
            try {
                result = joinPoint.proceed();
                return result;
            }catch(Throwable e){
                return new AuthorityException(500000,"system error");
            }
        }else{
            logger.info("~~~~~~~~~~~~~~~~~have no power");
            return null;
        }

    }


}

目标类

@Override
@RoleValid(role=RoleValidEnum.VIP3)
public void doVip3(String test,Vip3Param param){
    logger.info("ip3 办事~~~~~~~~~~~~~~~~~~~~~~~~~~~");
}

测试类

@Test
public void testForbid() throws Exception {
    Vip3Param param = new Vip3Param();
    param.setPower(RoleValidEnum.VIP4.getMsg());
    basicInfoService.doVip3("test",param);
}

run起来

2019-06-06 16:27:36 036 [main] INFO  com.yinyuecheng.jioencryption.aop.RoleValidAround - ~~~~~~~~~~limitPower:VIP3,~~~~~~~~~~~userPower:VIP4
2019-06-06 16:27:36 036 [main] INFO  c.y.j.service.impl.BasicInfoServiceImpl - ip3 办事~~~~~~~~~~~~~~~~~~~~~~~~~~~
2019-06-06 16:27:36 036 [Thread-2] INFO  o.s.scheduling.concurrent.ThreadPoolTaskExecutor - Shutting down ExecutorService 'applicationTaskExecutor'

震惊,aop类和目标类在一个线程里面跑(main线程 ,其实这个才最正常),这说明aop里面做的事情需要的消耗要完全算在整个程序的运行消耗里面,下面我们把aop里面加个线程休眠,更直观的看下aop对目标方法执行效率的影响

logger.info("~~~~~~~~~~limitPower:{},~~~~~~~~~~~userPower:{}",limitPower,userPower);
try {
    Thread.sleep(3000);
} catch (InterruptedException e) {
    e.printStackTrace();
}

再跑一次

2019-06-06 17:04:52 052 [main] INFO  com.yinyuecheng.jioencryption.aop.RoleValidAround - ~~~~~~~~~~limitPower:VIP3,~~~~~~~~~~~userPower:VIP4
2019-06-06 17:04:55 055 [main] INFO  c.y.j.service.impl.BasicInfoServiceImpl - ip3 办事~~~~~~~~~~~~~~~~~~~~~~~~~~~
2019-06-06 17:04:55 055 [Thread-2] INFO  o.s.scheduling.concurrent.ThreadPoolTaskExecutor - Shutting down ExecutorService 'applicationTaskExecutor'

很明显的看到执行时间被后置了三秒,所以aop实际上跟(从程序逻辑上来讲)在方法里面加上对应逻辑是一样的(但实际上动态代理也肯定是有资源消耗的)。
end

Logo

Authing 是一款以开发者为中心的全场景身份云产品,集成了所有主流身份认证协议,为企业和开发者提供完善安全的用户认证和访问管理服务

更多推荐