1
1
package org .springframework .context .bootstrap .generator .event ;
2
2
3
+ import java .io .IOException ;
4
+ import java .io .StringWriter ;
3
5
import java .util .List ;
6
+ import java .util .function .BiConsumer ;
4
7
5
8
import com .squareup .javapoet .CodeBlock ;
9
+ import com .squareup .javapoet .CodeBlock .Builder ;
6
10
import org .junit .jupiter .api .Test ;
7
11
8
12
import org .springframework .beans .factory .config .BeanDefinition ;
21
25
import org .springframework .context .bootstrap .generator .sample .event .SingleEventListener ;
22
26
import org .springframework .context .bootstrap .generator .sample .event .SingleTransactionalEventListener ;
23
27
import org .springframework .context .bootstrap .generator .sample .scope .SimpleServiceImpl ;
28
+ import org .springframework .context .bootstrap .generator .sample .visibility .ProtectedEventListenerConfiguration ;
24
29
import org .springframework .context .bootstrap .generator .test .CodeSnippet ;
30
+ import org .springframework .context .bootstrap .generator .test .TextAssert ;
31
+ import org .springframework .context .support .GenericApplicationContext ;
25
32
import org .springframework .transaction .event .TransactionalEventListenerFactory ;
26
33
import org .springframework .util .ReflectionUtils ;
27
34
@@ -39,16 +46,24 @@ void writeEventListenersRegistrationWithNoEventListener() {
39
46
DefaultListableBeanFactory beanFactory = prepareBeanFactory ();
40
47
beanFactory .registerBeanDefinition ("test" , BeanDefinitionBuilder .rootBeanDefinition (SimpleConfiguration .class )
41
48
.getBeanDefinition ());
42
- assertThat ( generateCode ( beanFactory ) ).isEmpty ();
49
+ assertGeneratedCode ( beanFactory , ( code , writerContext ) -> assertThat ( code ).isEmpty () );
43
50
}
44
51
45
52
@ Test
46
53
void writeEventListenersRegistrationWithSingleEventListener () {
47
54
DefaultListableBeanFactory beanFactory = prepareBeanFactory ();
48
55
beanFactory .registerBeanDefinition ("single" , BeanDefinitionBuilder .rootBeanDefinition (SingleEventListener .class )
49
56
.getBeanDefinition ());
50
- assertThat (generateCode (beanFactory )).lines ().containsExactly ("context.registerBean(\" org.springframework.aot.EventListenerRegistrar\" , EventListenerRegistrar.class, () -> new EventListenerRegistrar(context," ,
51
- " EventListenerMetadata.forBean(\" single\" , SingleEventListener.class).annotatedMethod(\" onStartup\" , ApplicationStartedEvent.class)" , "));" );
57
+ assertGeneratedCode (beanFactory , (code , writerContext ) -> {
58
+ assertThat (code ).lines ().contains ("context.registerBean(\" org.springframework.aot.EventListenerRegistrar\" , EventListenerRegistrar.class, "
59
+ + "() -> new EventListenerRegistrar(context, ContextBootstrapInitializer.getEventListenersMetadata()));" );
60
+ assertGeneratedCode (writerContext .getMainBootstrapClass ()).removeIndent (1 ).lines ().containsSequence (
61
+ "public static List<EventListenerMetadata> getEventListenersMetadata() {" ,
62
+ " return List.of(" ,
63
+ " EventListenerMetadata.forBean(\" single\" , SingleEventListener.class).annotatedMethod(\" onStartup\" , ApplicationStartedEvent.class)" ,
64
+ " );" ,
65
+ "}" );
66
+ });
52
67
}
53
68
54
69
@ Test
@@ -58,9 +73,35 @@ void writeEventListenersRegistrationWithEventListeners() {
58
73
.getBeanDefinition ());
59
74
beanFactory .registerBeanDefinition ("another" , BeanDefinitionBuilder .rootBeanDefinition (AnotherEventListener .class )
60
75
.getBeanDefinition ());
61
- assertThat (generateCode (beanFactory )).lines ().containsExactly ("context.registerBean(\" org.springframework.aot.EventListenerRegistrar\" , EventListenerRegistrar.class, () -> new EventListenerRegistrar(context," ,
62
- " EventListenerMetadata.forBean(\" test\" , SingleEventListener.class).annotatedMethod(\" onStartup\" , ApplicationStartedEvent.class)," ,
63
- " EventListenerMetadata.forBean(\" another\" , AnotherEventListener.class).annotatedMethod(\" onRefresh\" )" , "));" );
76
+ assertGeneratedCode (beanFactory , (code , writerContext ) -> assertGeneratedCode (writerContext .getMainBootstrapClass ())
77
+ .removeIndent (1 ).lines ().containsSequence (
78
+ "public static List<EventListenerMetadata> getEventListenersMetadata() {" ,
79
+ " return List.of(" ,
80
+ " EventListenerMetadata.forBean(\" test\" , SingleEventListener.class).annotatedMethod(\" onStartup\" , ApplicationStartedEvent.class)," ,
81
+ " EventListenerMetadata.forBean(\" another\" , AnotherEventListener.class).annotatedMethod(\" onRefresh\" )" ,
82
+ " );" ,
83
+ "}" ));
84
+ }
85
+
86
+ @ Test
87
+ void writeEventListenersRegistrationWithPackageProtectedEventListener () {
88
+ GenericApplicationContext context = new GenericApplicationContext (prepareBeanFactory ());
89
+ context .registerBeanDefinition ("configuration" , BeanDefinitionBuilder .rootBeanDefinition (ProtectedEventListenerConfiguration .class )
90
+ .getBeanDefinition ());
91
+ BuildTimeBeanDefinitionsRegistrar registrar = new BuildTimeBeanDefinitionsRegistrar ();
92
+ ConfigurableListableBeanFactory beanFactory = registrar .processBeanDefinitions (context );
93
+ assertGeneratedCode (beanFactory , (code , writerContext ) -> {
94
+ assertThat (code ).lines ().containsExactly ("context.registerBean(\" org.springframework.aot.EventListenerRegistrar\" , "
95
+ + "EventListenerRegistrar.class, () -> new EventListenerRegistrar(context, ContextBootstrapInitializer.getEventListenersMetadata()));" );
96
+ BootstrapClass bootstrapClass = writerContext .getBootstrapClass (ProtectedEventListenerConfiguration .class .getPackageName ());
97
+ assertGeneratedCode (bootstrapClass ).removeIndent (1 ).lines ().containsSequence (
98
+ "public static List<EventListenerMetadata> getEventListenersMetadata() {" ,
99
+ " return List.of(" ,
100
+ " EventListenerMetadata.forBean(\" protectedEventListener\" , ProtectedEventListener.class).annotatedMethod(\" onStartup\" , ApplicationStartedEvent.class)" ,
101
+ " );" ,
102
+ "}"
103
+ );
104
+ });
64
105
}
65
106
66
107
@ Test
@@ -72,10 +113,15 @@ void writeEventListenersRegistrationWithCustomEventListenerFactory() {
72
113
.getBeanDefinition ());
73
114
beanFactory .registerBeanDefinition ("transactional" , BeanDefinitionBuilder .rootBeanDefinition (SingleTransactionalEventListener .class )
74
115
.getBeanDefinition ());
75
- assertThat (generateCode (beanFactory )).lines ().containsExactly ("context.registerBean(\" org.springframework.aot.EventListenerRegistrar\" , EventListenerRegistrar.class, () -> new EventListenerRegistrar(context," ,
76
- " EventListenerMetadata.forBean(\" simple\" , SingleEventListener.class).annotatedMethod(\" onStartup\" , ApplicationStartedEvent.class)," ,
77
- " EventListenerMetadata.forBean(\" transactional\" , SingleTransactionalEventListener.class).eventListenerFactoryBeanName(\" internalTxEventListenerFactory\" ).annotatedMethod(\" onEvent\" , ApplicationEvent.class)" ,
78
- "));" );
116
+ assertGeneratedCode (beanFactory , (code , writerContext ) -> {
117
+ assertGeneratedCode (writerContext .getMainBootstrapClass ()).removeIndent (1 ).lines ().containsSequence (
118
+ "public static List<EventListenerMetadata> getEventListenersMetadata() {" ,
119
+ " return List.of(" ,
120
+ " EventListenerMetadata.forBean(\" simple\" , SingleEventListener.class).annotatedMethod(\" onStartup\" , ApplicationStartedEvent.class)," ,
121
+ " EventListenerMetadata.forBean(\" transactional\" , SingleTransactionalEventListener.class).eventListenerFactoryBeanName(\" internalTxEventListenerFactory\" ).annotatedMethod(\" onEvent\" , ApplicationEvent.class)" ,
122
+ " );" ,
123
+ "}" );
124
+ });
79
125
}
80
126
81
127
@ Test
@@ -84,10 +130,14 @@ void writeEventListenersRegistrationWithScopedProxy() {
84
130
context .register (SimpleServiceImpl .class );
85
131
BuildTimeBeanDefinitionsRegistrar registrar = new BuildTimeBeanDefinitionsRegistrar ();
86
132
ConfigurableListableBeanFactory beanFactory = registrar .processBeanDefinitions (context );
87
- assertThat (generateCode (beanFactory )).lines ().containsExactly (
88
- "context.registerBean(\" org.springframework.aot.EventListenerRegistrar\" , EventListenerRegistrar.class, () -> new EventListenerRegistrar(context," ,
89
- " EventListenerMetadata.forBean(\" simpleServiceImpl\" , SimpleServiceImpl.class).annotatedMethod(\" onContextRefresh\" )" ,
90
- "));" );
133
+ assertGeneratedCode (beanFactory , (code , writerContext ) -> {
134
+ assertGeneratedCode (writerContext .getMainBootstrapClass ()).removeIndent (1 ).lines ().containsSequence (
135
+ "public static List<EventListenerMetadata> getEventListenersMetadata() {" ,
136
+ " return List.of(" ,
137
+ " EventListenerMetadata.forBean(\" simpleServiceImpl\" , SimpleServiceImpl.class).annotatedMethod(\" onContextRefresh\" )" ,
138
+ " );" ,
139
+ "}" );
140
+ });
91
141
}
92
142
93
143
@ Test
@@ -97,22 +147,21 @@ void writeEventListenersRegistrationRegisterReflectionMetadata() {
97
147
.getBeanDefinition ());
98
148
beanFactory .registerBeanDefinition ("another" , BeanDefinitionBuilder .rootBeanDefinition (AnotherEventListener .class )
99
149
.getBeanDefinition ());
100
- EventListenerMethodRegistrationGenerator processor = new EventListenerMethodRegistrationGenerator (beanFactory );
101
- BootstrapWriterContext context = creteBootstrapContext ();
102
- processor .writeEventListenersRegistration (context , CodeBlock .builder ());
103
- List <NativeReflectionEntry > entries = context .getNativeConfigurationRegistry ().reflection ().getEntries ();
104
- assertThat (entries ).hasSize (2 );
105
- assertThat (entries ).anySatisfy ((entry ) -> {
106
- assertThat (entry .getType ()).isEqualTo (SingleEventListener .class );
107
- assertThat (entry .getMethods ()).containsOnly (
108
- ReflectionUtils .findMethod (SingleEventListener .class , "onStartup" , ApplicationStartedEvent .class ));
109
- assertThat (entry .getFields ()).isEmpty ();
110
- });
111
- assertThat (entries ).anySatisfy ((entry ) -> {
112
- assertThat (entry .getType ()).isEqualTo (AnotherEventListener .class );
113
- assertThat (entry .getMethods ()).containsOnly (
114
- ReflectionUtils .findMethod (AnotherEventListener .class , "onRefresh" ));
115
- assertThat (entry .getFields ()).isEmpty ();
150
+ assertGeneratedCode (beanFactory , (code , writerContext ) -> {
151
+ List <NativeReflectionEntry > entries = writerContext .getNativeConfigurationRegistry ().reflection ().getEntries ();
152
+ assertThat (entries ).hasSize (2 );
153
+ assertThat (entries ).anySatisfy ((entry ) -> {
154
+ assertThat (entry .getType ()).isEqualTo (SingleEventListener .class );
155
+ assertThat (entry .getMethods ()).containsOnly (
156
+ ReflectionUtils .findMethod (SingleEventListener .class , "onStartup" , ApplicationStartedEvent .class ));
157
+ assertThat (entry .getFields ()).isEmpty ();
158
+ });
159
+ assertThat (entries ).anySatisfy ((entry ) -> {
160
+ assertThat (entry .getType ()).isEqualTo (AnotherEventListener .class );
161
+ assertThat (entry .getMethods ()).containsOnly (
162
+ ReflectionUtils .findMethod (AnotherEventListener .class , "onRefresh" ));
163
+ assertThat (entry .getFields ()).isEmpty ();
164
+ });
116
165
});
117
166
}
118
167
@@ -122,13 +171,23 @@ private DefaultListableBeanFactory prepareBeanFactory() {
122
171
return beanFactory ;
123
172
}
124
173
125
- private CodeSnippet generateCode (ConfigurableListableBeanFactory beanFactory ) {
174
+ void assertGeneratedCode (ConfigurableListableBeanFactory beanFactory , BiConsumer < CodeSnippet , BootstrapWriterContext > generatedContent ) {
126
175
EventListenerMethodRegistrationGenerator processor = new EventListenerMethodRegistrationGenerator (beanFactory );
127
- return CodeSnippet .of ((code ) -> processor .writeEventListenersRegistration (creteBootstrapContext (), code ));
176
+ BootstrapWriterContext writerContext = new BootstrapWriterContext (BootstrapClass .of ("com.example" ));
177
+ Builder code = CodeBlock .builder ();
178
+ processor .writeEventListenersRegistration (writerContext , code );
179
+ generatedContent .accept (CodeSnippet .of (code .build ()), writerContext );
128
180
}
129
181
130
- private static BootstrapWriterContext creteBootstrapContext () {
131
- return new BootstrapWriterContext (BootstrapClass .of ("com.example" ));
182
+ private TextAssert assertGeneratedCode (BootstrapClass bootstrapClass ) {
183
+ try {
184
+ StringWriter out = new StringWriter ();
185
+ bootstrapClass .toJavaFile ().writeTo (out );
186
+ return new TextAssert (out .toString ());
187
+ }
188
+ catch (IOException ex ) {
189
+ throw new IllegalStateException (ex );
190
+ }
132
191
}
133
192
134
193
}
0 commit comments