首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 网站开发 > ASP >

AspectWeaver ——javassist具体运用

2012-11-04 
AspectWeaver ——javassist具体应用/* * Copyright 2004-2010 the Seasar Foundation and the Others. * *

AspectWeaver ——javassist具体应用

/* * Copyright 2004-2010 the Seasar Foundation and the Others. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * *     http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied. See the License for the specific language * governing permissions and limitations under the License. */package org.seasar.framework.aop.javassist;import java.lang.reflect.Field;import java.lang.reflect.Method;import java.util.ArrayList;import java.util.Collections;import java.util.HashSet;import java.util.List;import java.util.Map;import java.util.Set;import javassist.ClassPool;import org.aopalliance.intercept.MethodInterceptor;import org.aopalliance.intercept.MethodInvocation;import org.seasar.framework.aop.InterType;import org.seasar.framework.exception.NoSuchFieldRuntimeException;import org.seasar.framework.util.ClassLoaderUtil;import org.seasar.framework.util.ClassPoolUtil;import org.seasar.framework.util.FieldUtil;import org.seasar.framework.util.MethodUtil;/** * アスペクトを織り込むクラスです。 *  * @author koichik */public class AspectWeaver {    /**     * エンハンスされるクラスにつけるプレフィックス。     */    public static final String PREFIX_ENHANCED_CLASS = "$$";    /**     * エンハンスされるクラスにつけるサフィックス。     */    public static final String SUFFIX_ENHANCED_CLASS = "$$EnhancedByS2AOP$$";    /**     * エンハンスされる{@link MethodInvocation}につけるサフィックス。     */    public static final String SUFFIX_METHOD_INVOCATION_CLASS = "$$MethodInvocation$$";    /**     * super(親クラス)のメソッドを呼び出すときのサフィックス。     */    public static final String SUFFIX_INVOKE_SUPER_METHOD = "$$invokeSuperMethod$$";    /**     * エンハンスされるクラス名の {@link Set}     */    protected static final Set enhancedClassNames = Collections            .synchronizedSet(new HashSet());    /** * ターゲットクラス * @uml.property  name="targetClass" * @uml.associationEnd  multiplicity="(0 -1)" elementType="java.util.Collection" */    protected final Class targetClass;    /** * パラメータ * @uml.property  name="parameters" */    protected final Map parameters;    /** * エンハンスされるクラス名 * @uml.property  name="enhancedClassName" */    protected final String enhancedClassName;    /** * エンハンスされるクラスジェネレータ * @uml.property  name="enhancedClassGenerator" * @uml.associationEnd  multiplicity="(1 1)" */    protected final EnhancedClassGenerator enhancedClassGenerator;    /** * メソッド呼び出しクラスの   {@link List}  * @uml.property  name="methodInvocationClassList" * @uml.associationEnd  multiplicity="(0 -1)" elementType="java.lang.Class" */    protected final List methodInvocationClassList = new ArrayList();    /** * エンハンスされるクラス * @uml.property  name="enhancedClass" * @uml.associationEnd  multiplicity="(0 -1)" elementType="java.util.Collection" */    protected Class enhancedClass;    /** * クラスプール * @uml.property  name="classPool" * @uml.associationEnd  multiplicity="(1 1)" */    protected ClassPool classPool;    /**     * {@link AspectWeaver}を作成します。     *      * @param targetClass     * @param parameters     */    public AspectWeaver(final Class targetClass, final Map parameters) {        this.targetClass = targetClass;        this.parameters = parameters;        classPool = ClassPoolUtil.getClassPool(targetClass);        enhancedClassName = getEnhancedClassName();        //根据targetClass,产生enhancedClass的CtClass形式(由javassist负责)        enhancedClassGenerator = new EnhancedClassGenerator(classPool,                targetClass, enhancedClassName);    }    /**     * {@link MethodInterceptor}を設定します。     *      * @param method     * @param interceptors     */    public void setInterceptors(final Method method,            final MethodInterceptor[] interceptors) {        final String methodInvocationClassName = getMethodInvocationClassName(method);                //创建methodInvocationClass  此时还是CtClass(javassist的形式)        final MethodInvocationClassGenerator methodInvocationGenerator = new MethodInvocationClassGenerator(                classPool, methodInvocationClassName, enhancedClassName);        final String invokeSuperMethodName = createInvokeSuperMethod(method);        methodInvocationGenerator.createProceedMethod(method,                invokeSuperMethodName);                //这里产生enhancedClass 和  MethodInvocationClass的联系,参见EnhancedClassGenerator的createTargetMethodSource方法        enhancedClassGenerator.createTargetMethod(method,                methodInvocationClassName);                //methodInvocationClass产生Class(还没实例 化。因此不知道由构造函数传入的二属性:target, arguments)        final Class methodInvocationClass = methodInvocationGenerator                .toClass(ClassLoaderUtil.getClassLoader(targetClass));        //设置各种属性的值(targetClass 只有 enhancedClass 存在的情况下才会设置)        setStaticField(methodInvocationClass, "method", method);        setStaticField(methodInvocationClass, "interceptors", interceptors);        setStaticField(methodInvocationClass, "parameters", parameters);        methodInvocationClassList.add(methodInvocationClass);    }    /**     * {@link InterType}を追加します。     *      * @param interTypes     */    public void setInterTypes(final InterType[] interTypes) {        if (interTypes == null) {            return;        }        for (int i = 0; i < interTypes.length; ++i) {            enhancedClassGenerator.applyInterType(interTypes[i]);        }    }    /**     * クラスを生成します。     *      * @return 生成されたクラス     */    public Class generateClass() {        if (enhancedClass == null) {            //CtClass->Class            enhancedClass = enhancedClassGenerator.toClass(ClassLoaderUtil                    .getClassLoader(targetClass));                                    //设置methodInvocationClass的目标class,这个是找到被代理的类的方法,很重要,具体使用可见各个Interceptor的invoke方法            //注意和target属性区分            for (int i = 0; i < methodInvocationClassList.size(); ++i) {                final Class methodInvocationClass = (Class) methodInvocationClassList                        .get(i);                setStaticField(methodInvocationClass, "targetClass",                        targetClass);            }        }        return enhancedClass;    }    /**     * エンハンスされたクラス名を返します。     *      * @return エンハンスされたクラス名     */    public String getEnhancedClassName() {        final StringBuffer buf = new StringBuffer(200);        final String targetClassName = targetClass.getName();        final Package pkg = targetClass.getPackage();        if (targetClassName.startsWith("java.")                || (pkg != null && pkg.isSealed())) {            buf.append(PREFIX_ENHANCED_CLASS);        }        buf.append(targetClassName).append(SUFFIX_ENHANCED_CLASS).append(                Integer.toHexString(hashCode()));        final int length = buf.length();        for (int i = 0; enhancedClassNames.contains(new String(buf)); ++i) {            buf.setLength(length);            buf.append("_").append(i);        }        String name = new String(buf);        enhancedClassNames.add(name);        return name;    }    /**     * エンハンスされた{@link MethodInvocation}のクラス名を返します。     *      * @param method     * @return     */    public String getMethodInvocationClassName(final Method method) {        return enhancedClassName + SUFFIX_METHOD_INVOCATION_CLASS                + method.getName() + methodInvocationClassList.size();    }    /**     * superクラスのメソッドを呼び出すためのメソッド名を作成します。     *      * @param method     * @return     */    public String createInvokeSuperMethod(final Method method) {        final String invokeSuperMethodName = PREFIX_ENHANCED_CLASS                + method.getName() + SUFFIX_INVOKE_SUPER_METHOD;        if (!MethodUtil.isAbstract(method)) {            enhancedClassGenerator.createInvokeSuperMethod(method,                    invokeSuperMethodName);        }        return invokeSuperMethodName;    }    /**     * static filedに値を設定します。     *      * @param clazz     * @param name     * @param value     */    public void setStaticField(final Class clazz, final String name,            final Object value) {        try {            final Field field = clazz.getDeclaredField(name);            field.setAccessible(true);            FieldUtil.set(field, name, value);            field.setAccessible(false);        } catch (final NoSuchFieldException e) {            throw new NoSuchFieldRuntimeException(enhancedClass, name, e);        }    }}

热点排行