Spring が変換された注釈を認識できるように、クラスを変換しようとしています。これにより、@Entity アノテーションを動的に注入して、Spring Boot がそれをデータ使用のためのマネージド型として登録できるようになります。
アノテーション変換は機能しますが、Spring Boot は変換されたバージョンが見つからないファイル jar レベルでパッケージ スキャンを実行しているようです。これは、JAR 自体内のクラス ファイルの入力ストリームを分析しているため、Spring がアノテーションを認識していないことを意味します。
初期のばね候補コンポーネントのスキャンは次のとおりです。
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 の範囲外ですか?
ClassLoader cl = getClassLoader();
Enumeration<URL> resourceUrls = (cl != null ? cl.getResources(path) : ClassLoader.getSystemResources(path));
リソースをロードした後、Spring はクラスのメタデータをロードします (アノテーションが欠落している場合)
MetadataReader metadataReader = this.metadataReaderFactory.getMetadataReader(resource);
上記の getMetadataReader メソッド呼び出しは、最終的に
final class SimpleMetadataReader implements MetadataReader
ASM ClassReader を使用して、クラスと注釈のメタデータにアクセスします。これは明らかに、Bytebuddy によって配置された @Entity アノテーションを検出しません。
Classloader を Bytebuddy にリンクするか、Springs SimpleMetadataReader をオーバーライドして、独自の実装を ByteBuddy でサポートする必要があるかどうかはわかりません。
助言がありますか?AgentBuilder を使用して注釈を変換し、Spring Boot の起動前に実行しています。
public static void main(String[] args) {
EntityAgent.install(ByteBuddyAgent.install());
InversionContainer.startInversion(args);
}
完全を期すために私のByteBuddy Impl:
**
* 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 をレビューしました
実装の詳細が必要な場合はお知らせください。スプリング コンポーネント アノテーションを使用してクラスを計測できるように、bytebuddy とスプリングをきれいに統合したいと考えています。