首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >ByteBuddy @Entity注释对Spring Boot ClassPathBeanDefinitionScanner basePackages扫描不可见

ByteBuddy @Entity注释对Spring Boot ClassPathBeanDefinitionScanner basePackages扫描不可见
EN

Stack Overflow用户
提问于 2016-05-24 08:51:08
回答 1查看 805关注 0票数 1

我正在尝试转换类,以便Spring可以看到转换后的注释。这将允许我动态注入@Entity注释,以便Spring Boot将其注册为托管类型以供数据使用。

注释转换可以工作,但Spring Boot似乎是在file-jar级别执行包扫描,缺少转换后的版本。这意味着Spring看不到注释,因为它正在分析JAR本身中的类文件的输入流。

初始弹簧候选组件扫描如下:

代码语言:javascript
运行
复制
     public Set<BeanDefinition> findCandidateComponents(String basePackage) {
        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

        Resource[] resources = this.resourcePatternResolver.getResources(packageSearchPath);

        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

        MetadataReader metadataReader = this.metadataReaderFactory.getMetadataReader(resource);

        if (isCandidateComponent(metadataReader)) {

        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

getResources调用最终以PathMatchingResourcePatternResolver - doFindAllClassPathResources结束

在这种情况下,Springs类加载器是否超出了ByteBuddy的范围?

代码语言:javascript
运行
复制
ClassLoader cl = getClassLoader();
    Enumeration<URL> resourceUrls = (cl != null ? cl.getResources(path) : ClassLoader.getSystemResources(path));

加载资源后,Spring加载类元数据(缺少注释)

代码语言:javascript
运行
复制
MetadataReader metadataReader = this.metadataReaderFactory.getMetadataReader(resource);

上面的getMetadataReader方法调用最终以

代码语言:javascript
运行
复制
final class SimpleMetadataReader implements MetadataReader 

它使用ASM ClassReader来访问类和注释元数据。这显然找不到Bytebuddy放置的@Entity注释。

我不确定我是应该以某种方式将类加载器链接到字节伙伴中,还是应该覆盖Springs SimpleMetadataReader来让我自己的实现由ByteBuddy支持。

有什么建议吗?我正在使用AgentBuilder来转换注释,并在spring启动之前运行它。

代码语言:javascript
运行
复制
public static void main(String[] args) {
    EntityAgent.install(ByteBuddyAgent.install());
    InversionContainer.startInversion(args);
}

我的ByteBuddy实现了完整性:

代码语言:javascript
运行
复制
**
* Transform all Non-Abstract Classes which extend BaseEntity
* to have the annotation Entity
*/
public class EntityAgent {

    /**
     * Installs the agent builder to the instrumentation API.
     */
    public static void install(Instrumentation inst) {
        createAgentBuilder().installOn(inst);
    }

    /**
      * Creates the AgentBuilder that will redefine any class extending BaseEntity
     */
    private static AgentBuilder createAgentBuilder() {
        return new AgentBuilder.Default()
                .with(toSystemError())
                .with(AgentBuilder.RedefinitionStrategy.REDEFINITION)
                .with(AgentBuilder.InitializationStrategy.SelfInjection.EAGER)
                .with(AgentBuilder.TypeStrategy.Default.REDEFINE)
                .type(getClassMatcher())
                .transform(getTransformer());
    }

    /**
     * Set Entity annotation on Class
     */
    private static AgentBuilder.Transformer getTransformer() {
        return (builder, typeDescription, classloader) -> builder.annotateType(AnnotationDescription.Builder.ofType(Entity.class).build());
    }

    /**
     * Find any non-abstract class that extends BaseEntity
     */
    private static ElementMatcher.Junction<TypeDescription> get ClassMatcher() {
        return ElementMatchers.isSubTypeOf(BaseEntity.class).and(ElementMatchers.not(ElementMatchers.isAbstract()));
    }
}

我复习了Unable to instrument apache httpclient using javaagent for spring boot uber jar application

如果你想要更多的实现细节,请告诉我。我想干净利落地将integrate与spring集成在一起,这样我就可以用spring组件注释来检测类了。

EN

回答 1

Stack Overflow用户

发布于 2016-05-24 20:20:03

“问题”是Spring查看的是原始类,而不是加载的类。Byte Buddy注册了一个Java代理,该代理在加载类时对其进行转换,但保留Spring Boot无法识别的原始类文件。

另一个问题是Spring在启动时和装入类之前会检查jar文件。这意味着当Spring收集它的实体时,Byte Buddy代理甚至还没有激活。

相反,Spring应该调查加载的类,因为类加载器可能甚至不提供类文件,但我假设它们试图保留导致这种结果的类加载顺序。

唯一的替代方法是要求Byte Buddy在启动时重写任何相关的jar文件。您将需要解析类路径上的任何资源,并重新定义包含该文件的jars。在关闭时,您应该通过复制回原始jar状态来重置状态。

理想情况下,Spring会添加一个选项,通过查看加载的类来扫描,而不是解析类文件,因为这两种方法都有优缺点。根据我的经验,查看加载的类无论如何都会更有性能,因为它避免了IO重复,因此该选项可以使用例受益于代理识别之外的用例。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/37402782

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档