<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>绿色记忆 &#187; Javassist</title>
	<atom:link href="https://blog.gmem.cc/tag/javassist/feed" rel="self" type="application/rss+xml" />
	<link>https://blog.gmem.cc</link>
	<description></description>
	<lastBuildDate>Thu, 30 Apr 2026 03:05:57 +0000</lastBuildDate>
	<language>en-US</language>
		<sy:updatePeriod>hourly</sy:updatePeriod>
		<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.9.14</generator>
	<item>
		<title>Aspject加载时织入示例</title>
		<link>https://blog.gmem.cc/aspectj-load-time-weave-in</link>
		<comments>https://blog.gmem.cc/aspectj-load-time-weave-in#comments</comments>
		<pubDate>Sat, 13 Jul 2013 07:01:54 +0000</pubDate>
		<dc:creator><![CDATA[Alex]]></dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[AspectJ]]></category>
		<category><![CDATA[Javassist]]></category>

		<guid isPermaLink="false">http://blog.gmem.cc/?p=1678</guid>
		<description><![CDATA[<p>问题场景 最近的一个使用DDD风格建模的项目中，遇到这样的一个场景： 领域类的抽象类层次，作为Hibernate实体类使用，由于其包含了一些业务逻辑，需要Spring依赖注入的支持，故使用了@Configurable注解+AspectJ编译时织入的方式 具体领域类，一般没有业务逻辑，但是类数量较多，故使用Javassist进行自动的类生成 运行的时候出现问题了，使用Javassist生成的具体领域类，无法注入依赖，尽管其父类上有@Configurable注解。经过跟踪，发现子类也必须进行织入才能正常的进行依赖注入，那么，如何在生成字节码的时候，同时织入AOP逻辑呢？ AspectJ字节码织入工具类 其实AspectJ已经提供了加载时织入的API，下面这个工具类，即可用于织入任何指定的切面： [crayon-69f415a0a5831394329840/] 该工具类的一个实例，专门用于织入Spring aspects： [crayon-69f415a0a5839339746925/] 在生成字节码时织入Spring-aspects 下面的例子中，首先生成了类的基本骨架，然后调用AspectJBytecodeWeaver进行织入。 [crayon-69f415a0a583c143889858/]</p>
<p>The post <a rel="nofollow" href="https://blog.gmem.cc/aspectj-load-time-weave-in">Aspject加载时织入示例</a> appeared first on <a rel="nofollow" href="https://blog.gmem.cc">绿色记忆</a>.</p>
]]></description>
				<content:encoded><![CDATA[<div class="wri_content_clear_both"><div class="blog_h2"><span class="graybg">问题场景</span></div>
<p>最近的一个使用DDD风格建模的项目中，遇到这样的一个场景：</p>
<ol>
<li>领域类的抽象类层次，作为Hibernate实体类使用，由于其包含了一些业务逻辑，需要Spring依赖注入的支持，故使用了@Configurable注解+AspectJ编译时织入的方式</li>
<li>具体领域类，一般没有业务逻辑，但是类数量较多，故使用Javassist进行自动的类生成</li>
</ol>
<p>运行的时候出现问题了，使用Javassist生成的具体领域类，无法注入依赖，尽管其父类上有@Configurable注解。经过跟踪，发现子类也必须进行织入才能正常的进行依赖注入，那么，如何在生成字节码的时候，同时织入AOP逻辑呢？</p>
<div class="blog_h2"><span class="graybg">AspectJ字节码织入工具类</span></div>
其实AspectJ已经提供了加载时织入的API，下面这个工具类，即可用于织入任何指定的切面：<br />
<pre class="crayon-plain-tag">import java.lang.instrument.IllegalClassFormatException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import org.aspectj.weaver.loadtime.Aj;
import org.aspectj.weaver.loadtime.DefaultWeavingContext;
import org.aspectj.weaver.loadtime.definition.Definition;
import org.aspectj.weaver.tools.WeavingAdaptor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Weave byte codes at load time.
 * 
 * @author Andrica Silviu
 * @author WangZhen
 */
public class AspectJBytecodeWeaver
{

    private static final Logger LOGGER = LoggerFactory.getLogger( AspectJBytecodeWeaver.class );

    private class DynamicAspectWeavingContext extends DefaultWeavingContext
    {

        public DynamicAspectWeavingContext( ClassLoader loader )
        {
            super( loader );
        }

        public List&lt;Definition&gt; getDefinitions( ClassLoader loader, WeavingAdaptor adaptor )
        {
            List&lt;Definition&gt; definitions = new ArrayList&lt;Definition&gt;();
            Definition d = new Definition();
            for ( String aspectName : aspectNames )
            {
                d.getAspectClassNames().add( aspectName );
            }
            d.appendWeaverOptions( "-Xjoinpoints:synchronization" );
            if ( LOGGER.isDebugEnabled() )
            {
                d.appendWeaverOptions( "-showWeaveInfo" );
            }
            definitions.add( d );
            return definitions;
        }

    }

    private final Map&lt;ClassLoader, Aj&gt; mapFromClassLoaderToAj;

    private final String[]             aspectNames;

    public AspectJBytecodeWeaver( String[] aspectName )
    {
        mapFromClassLoaderToAj = new ConcurrentHashMap&lt;ClassLoader, Aj&gt;();
        this.aspectNames = aspectName;
    }

    /**
     * Weaving delegation
     * 
     * @param loader
     *            the defining class loader
     * @param className
     *            the name of class beeing loaded
     * @param bytes
     *            the bytecode before weaving
     * @return the weaved bytecode
     */
    public byte[] weave( ClassLoader loader, String className, byte[] bytes ) throws IllegalClassFormatException
    {
        if ( className.replace( "/", "." ).equals( aspectNames ) )
        {
            return null;
        }
        Aj aj = getAj( loader );
        if ( LOGGER.isDebugEnabled() )
        {
            LOGGER.debug( "Weaving class : {} with aspect(s) :{}", className, Arrays.deepToString( aspectNames ) );
        }
        byte[] b = aj.preProcess( className, bytes, loader );
        return b;
    }

    private Aj getAj( ClassLoader loader )
    {
        if ( mapFromClassLoaderToAj.containsKey( loader ) )
        {
            return mapFromClassLoaderToAj.get( loader );
        }
        Aj aj = new Aj( new DynamicAspectWeavingContext( loader ) );
        mapFromClassLoaderToAj.put( loader, aj );
        return aj;
    }
}</pre><br />
该工具类的一个实例，专门用于织入Spring aspects：<br />
<pre class="crayon-plain-tag">public class SpringAspectJ
{
    private static final String               ASPECT_BEAN_CONFIG =
                                                                         "org.springframework.beans.factory.aspectj.AnnotationBeanConfigurerAspect";

    private static final String               ASPECT_SCHEDULING  =
                                                                         "org.springframework.scheduling.aspectj.AnnotationAsyncExecutionAspect";

    private static final String               ASPECT_TRANSACTION =
                                                                         "org.springframework.transaction.aspectj.AnnotationTransactionAspect";

    private static final String               ASPECT_CACHE       =
                                                                         "org.springframework.cache.aspectj.AnnotationCacheAspect";

    public static final AspectJBytecodeWeaver WEAVER             = new AspectJBytecodeWeaver( new String[] {
                                                                 ASPECT_BEAN_CONFIG, ASPECT_SCHEDULING,
                                                                 ASPECT_TRANSACTION, ASPECT_CACHE } );
}</pre>
<div class="blog_h2"><span class="graybg">在生成字节码时织入Spring-aspects</span></div>
下面的例子中，首先生成了类的基本骨架，然后调用AspectJBytecodeWeaver进行织入。<br />
<pre class="crayon-plain-tag">ClassPool cp = ClassPool.getDefault();
ClassPath clsPath = new ClassClassPath( this.getClass() );
cp.insertClassPath( clsPath );
CtClass cc = cp.makeClass( getClassName() );
if ( StringUtils.isNotBlank( getSuperClassName() ) )
{
    cc.setSuperclass( cp.get( getSuperClassName() ) );
}
ClassFile cf = cc.getClassFile();
ConstPool constPool = cf.getConstPool();

if ( isWeaveSpringAspects() )
{
    ClassLoader loader = Thread.currentThread().getContextClassLoader();
    try
    {
        //织入Spring切面
        byte[] b = SpringAspectJ.WEAVER.weave( loader, getClassName(), cc.toBytecode() );
        cc.detach();
        cc = cp.makeClass( new ByteArrayInputStream( b ) );
    }
    catch ( IOException e )
    {
        throw new RuntimeException( e.getMessage(), e );
    }
}
Class&lt;?&gt; c = cc.toClass();
cc.detach();
return c;</pre>
</div><p>The post <a rel="nofollow" href="https://blog.gmem.cc/aspectj-load-time-weave-in">Aspject加载时织入示例</a> appeared first on <a rel="nofollow" href="https://blog.gmem.cc">绿色记忆</a>.</p>
]]></content:encoded>
			<wfw:commentRss>https://blog.gmem.cc/aspectj-load-time-weave-in/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
