[心缘地方]同学录
首页 | 功能说明 | 站长通知 | 最近更新 | 编码查看转换 | 代码下载 | 常见问题及讨论 | 《深入解析ASP核心技术》 | 王小鸭自动发工资条VBA版
登录系统:用户名: 密码: 如果要讨论问题,请先注册。

[备忘]org.springframework.aop.support.DefaultBeanFactoryPointcutAdvisor占内存

上一篇:[备忘]postgresql的to_char里日期格式yyyy-MM-dd hh24:MI:ss
下一篇:[备忘]pointcut的表达式里为什么可以写and not or

添加日期:2024/5/29 19:19:27 快速返回   返回列表 阅读210次
org.springframework.aop.support.DefaultBeanFactoryPointcutAdvisor占内存,


<aop:config>
  <aop:advisor pointcut="within(cn.com.tcsl.aaa..*.service..*)" advice-ref="transactionAdviceAAA" />
  <aop:advisor pointcut="within(cn.com.tcsl.bbb..*.service..*)" advice-ref="transactionAdviceAAA" />
</aop:config>
由于工程类较多,每个DefaultBeanFactoryPointcutAdvisor对象大概占用20MB,6个120MB。

每个DefaultBeanFactoryPointcutAdvisor里面有一个org.springframework.aop.aspectj.AspectJExpressionPointcut对象,
里面有个map,保存着所有匹配的method。

发现每个Map里大概2.5万个method对象,
6个Advisor就是6*2.5万。

挨个看,发现不符合表达式的method也在里面,怀疑aop的匹配有bug,所以看代码。

从DefaultBeanFactoryPointcutAdvisor类下断点,找到了
org.springframework.aop.support.AopUtils类


/**
     * Determine the sublist of the {@code candidateAdvisors} list
     * that is applicable to the given class.
     * @param candidateAdvisors the Advisors to evaluate
     * @param clazz the target class
     * @return sublist of Advisors that can apply to an object of the given class
     * (may be the incoming List as-is)
     */
    public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) {
        if (candidateAdvisors.isEmpty()) {
            return candidateAdvisors;
        }
        List<Advisor> eligibleAdvisors = new LinkedList<Advisor>();
        for (Advisor candidate : candidateAdvisors) {
            if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) {
                eligibleAdvisors.add(candidate);
            }
        }
        boolean hasIntroductions = !eligibleAdvisors.isEmpty();
        for (Advisor candidate : candidateAdvisors) {
            if (candidate instanceof IntroductionAdvisor) {
                // already processed
                continue;
            }
            if (canApply(candidate, clazz, hasIntroductions)) {
                eligibleAdvisors.add(candidate);
            }
        }
        return eligibleAdvisors;
    }


就是遍历class,看它是否符合某个Advisor的要求。

    
/**
     * Can the given pointcut apply at all on the given class?
     * <p>This is an important test as it can be used to optimize
     * out a pointcut for a class.
     * @param pc the static or dynamic pointcut to check
     * @param targetClass the class to test
     * @param hasIntroductions whether or not the advisor chain
     * for this bean includes any introductions
     * @return whether the pointcut can apply on any method
     */
    public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) {
        Assert.notNull(pc, "Pointcut must not be null");
        if (!pc.getClassFilter().matches(targetClass)) {
            return false;
        }

        MethodMatcher methodMatcher = pc.getMethodMatcher();
        IntroductionAwareMethodMatcher introductionAwareMethodMatcher = null;
        if (methodMatcher instanceof IntroductionAwareMethodMatcher) {
            introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher) methodMatcher;
        }

        Set<Class<?>> classes = new LinkedHashSet<Class<?>>(ClassUtils.getAllInterfacesForClassAsSet(targetClass));
        classes.add(targetClass);
        for (Class<?> clazz : classes) {
            Method[] methods = clazz.getMethods();
            for (Method method : methods) {
                if ((introductionAwareMethodMatcher != null &&
                        introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions)) ||
                        methodMatcher.matches(method, targetClass)) {
                    return true;
                }
            }
        }

        return false;
    }



if (!pc.getClassFilter().matches(targetClass)) {
    return false;
}
这个先过滤了一下类,看是否符合表达式。
调到了org.aspectj.weaver.internal.tools.PointcutExpressionImpl

    
    public boolean couldMatchJoinPointsInType(Class aClass) {
        ResolvedType matchType = world.resolve(aClass.getName());
        ReflectionFastMatchInfo info = new ReflectionFastMatchInfo(matchType, null, this.matchContext, world);
        boolean couldMatch = pointcut.fastMatch(info).maybeTrue();
        if (MATCH_INFO) {
            System.out.println("MATCHINFO: fast match for '" + this.expression + "' against '" + aClass.getName() + "': "
                    + couldMatch);
        }
        return couldMatch;
    }


调的org.aspectj.weaver.patterns.KindedPointcut类,
注意,这里是一个fastMatch(info),后面带了一个maybeTrue(),
fastMatch里只检查了精确匹配和注解那种的,其余都返回MAYBE了,然后返回true了。
就是搞不清的,都算匹配了。
    
@Pointcut("execution(* com.aaaa.service.*(..))")
实际class是com.bbbb.service.XX,也算成功了。
真是莫名其妙,起码检查一下包路径吧。
    
匹配之后,后面走method匹配,没看明白。
    
-------------------
包括子包
@Pointcut("within(com.aaa..*)")

改成within后走WithinPointcut类,


public FuzzyBoolean fastMatch(FastMatchInfo info) {
        if (typePattern.annotationPattern instanceof AnyAnnotationTypePattern) {
            return isWithinType(info.getType());
        }
        return FuzzyBoolean.MAYBE;
    }


比较了类名,所以最终map里method是对的,只有100多个。

很美好,是吧,换成within后启动慢了10多秒,见鬼了。
折腾好久,发现升级aspectjweaver版本就好了。
    
 

评论 COMMENTS
没有评论 No Comments.

添加评论 Add new comment.
昵称 Name:
评论内容 Comment:
验证码(不区分大小写)
Validation Code:
(not case sensitive)
看不清?点这里换一张!(Change it here!)
 
评论由管理员查看后才能显示。the comment will be showed after it is checked by admin.
CopyRight © 心缘地方 2005-2999. All Rights Reserved