1616
1717package  org .springframework .web .service .registry ;
1818
19+ import  java .util .Arrays ;
20+ import  java .util .function .Consumer ;
21+ 
22+ import  org .jspecify .annotations .Nullable ;
23+ 
24+ import  org .springframework .beans .BeanUtils ;
25+ import  org .springframework .beans .factory .annotation .AnnotatedBeanDefinition ;
26+ import  org .springframework .beans .factory .config .BeanDefinition ;
1927import  org .springframework .core .annotation .MergedAnnotation ;
28+ import  org .springframework .core .io .ResourceLoader ;
2029import  org .springframework .core .type .AnnotationMetadata ;
30+ import  org .springframework .core .type .classreading .CachingMetadataReaderFactory ;
31+ import  org .springframework .core .type .classreading .MetadataReader ;
32+ import  org .springframework .core .type .classreading .MetadataReaderFactory ;
33+ import  org .springframework .util .Assert ;
2134import  org .springframework .util .ClassUtils ;
2235import  org .springframework .util .ObjectUtils ;
36+ import  org .springframework .util .StringUtils ;
37+ import  org .springframework .util .function .ThrowingFunction ;
38+ import  org .springframework .web .service .registry .HttpServiceGroup .ClientType ;
2339
2440/** 
2541 * Built-in implementation of {@link AbstractHttpServiceRegistrar} that uses 
3349 */ 
3450class  ImportHttpServiceRegistrar  extends  AbstractHttpServiceRegistrar  {
3551
52+ 	private  @ Nullable  MetadataReaderFactory  metadataReaderFactory ;
53+ 
54+ 	@ Override 
55+ 	public  void  setResourceLoader (ResourceLoader  resourceLoader ) {
56+ 		super .setResourceLoader (resourceLoader );
57+ 		this .metadataReaderFactory  = new  CachingMetadataReaderFactory (resourceLoader );
58+ 	}
59+ 
3660	@ Override 
3761	protected  void  registerHttpServices (GroupRegistry  registry , AnnotationMetadata  metadata ) {
3862
@@ -50,7 +74,7 @@ protected void registerHttpServices(GroupRegistry registry, AnnotationMetadata m
5074	private  void  processImportAnnotation (MergedAnnotation <?> annotation , GroupRegistry  groupRegistry ,
5175			AnnotationMetadata  metadata ) {
5276
53- 		String   groupName  = annotation . getString ( "group" );
77+ 		ImportHttpServices . GroupProvider   groupProvider  = getGroupProvider ( annotation );
5478		HttpServiceGroup .ClientType  clientType  = annotation .getEnum ("clientType" , HttpServiceGroup .ClientType .class );
5579		Class <?>[] types  = annotation .getClassArray ("types" );
5680		Class <?>[] basePackageClasses  = annotation .getClassArray ("basePackageClasses" );
@@ -60,10 +84,70 @@ private void processImportAnnotation(MergedAnnotation<?> annotation, GroupRegist
6084			basePackages  = new  String [] { ClassUtils .getPackageName (metadata .getClassName ()) };
6185		}
6286
63- 		groupRegistry .forGroup (groupName , clientType )
64- 				.register (types )
65- 				.detectInBasePackages (basePackageClasses )
66- 				.detectInBasePackages (basePackages );
87+ 		registerHttpServices (groupRegistry , groupProvider , clientType , types , basePackageClasses , basePackages );
88+ 	}
89+ 
90+ 	private  ImportHttpServices .GroupProvider  getGroupProvider (MergedAnnotation <?> annotation ) {
91+ 		String  group  = annotation .getString ("group" );
92+ 		Class <?> groupProvider  = annotation .getClass ("groupProvider" );
93+ 		if  (groupProvider  == ImportHttpServices .GroupProvider .class ) {
94+ 			return  new  FixedGroupProvider (StringUtils .hasText (group ) ? group  : HttpServiceGroup .DEFAULT_GROUP_NAME );
95+ 		}
96+ 		Assert .state (!StringUtils .hasText (group ), "'group' cannot be mixed with 'groupProvider'" );
97+ 		return  (ImportHttpServices .GroupProvider ) BeanUtils .instantiateClass (groupProvider );
98+ 	}
99+ 
100+ 	private  void  registerHttpServices (GroupRegistry  groupRegistry ,
101+ 			ImportHttpServices .GroupProvider  groupProvider , ClientType  clientType , Class <?>[] types ,
102+ 			Class <?>[] basePackageClasses , String [] basePackages ) {
103+ 
104+ 		if  (groupProvider  instanceof  FixedGroupProvider  fixedGroupProvider ) {
105+ 			String  groupName  = fixedGroupProvider .group ();
106+ 			groupRegistry .forGroup (groupName , clientType )
107+ 					.register (types )
108+ 					.detectInBasePackages (basePackageClasses )
109+ 					.detectInBasePackages (basePackages );
110+ 		}
111+ 		else  {
112+ 			MetadataReaderFactory  metadataReaderFactory  = (this .metadataReaderFactory  != null ) ?
113+ 					this .metadataReaderFactory  : new  CachingMetadataReaderFactory ();
114+ 
115+ 			Consumer <AnnotationMetadata > register  = metadata  -> {
116+ 				String  group  = groupProvider .group (metadata );
117+ 				if  (group  != null ) {
118+ 					groupRegistry .forGroup (group , clientType ).registerTypeNames (metadata .getClassName ());
119+ 				}
120+ 			};
121+ 
122+ 			Arrays .stream (types )
123+ 					.map (Class ::getName )
124+ 					.map (ThrowingFunction .of (metadataReaderFactory ::getMetadataReader ))
125+ 					.map (MetadataReader ::getAnnotationMetadata )
126+ 					.forEach (register );
127+ 			Arrays .stream (basePackageClasses )
128+ 					.map (Class ::getPackageName )
129+ 					.flatMap (this ::findHttpServices )
130+ 					.map (this ::getMetadata )
131+ 					.forEach (register );
132+ 			Arrays .stream (basePackages )
133+ 					.flatMap (this ::findHttpServices )
134+ 					.map (this ::getMetadata )
135+ 					.forEach (register );
136+ 		}
137+ 	}
138+ 
139+ 	private  AnnotationMetadata  getMetadata (BeanDefinition  beanDefinition ) {
140+ 		Assert .state (beanDefinition  instanceof  AnnotatedBeanDefinition ,
141+ 				"AnnotatedBeanDefinition required when using 'groupProvider'" );
142+ 		return  ((AnnotatedBeanDefinition ) beanDefinition ).getMetadata ();
143+ 	}
144+ 
145+ 	private  static  record  FixedGroupProvider (String  group ) implements  ImportHttpServices .GroupProvider  {
146+ 
147+ 		@ Override 
148+ 		public  String  group (AnnotationMetadata  metadata ) {
149+ 			return  this .group ;
150+ 		}
67151	}
68152
69153}
0 commit comments