4949import org .springframework .core .annotation .MergedAnnotations .SearchStrategy ;
5050import org .springframework .core .env .Environment ;
5151import org .springframework .util .Assert ;
52+ import org .springframework .util .ClassUtils ;
5253import org .springframework .util .CollectionUtils ;
5354import org .springframework .util .LinkedMultiValueMap ;
5455import org .springframework .util .MultiValueMap ;
@@ -140,8 +141,9 @@ private Collection<EndpointBean> createEndpointBeans() {
140141 }
141142
142143 private EndpointBean createEndpointBean (String beanName ) {
143- Object bean = this .applicationContext .getBean (beanName );
144- return new EndpointBean (this .applicationContext .getEnvironment (), beanName , bean );
144+ Class <?> beanType = ClassUtils .getUserClass (this .applicationContext .getType (beanName , false ));
145+ Supplier <Object > beanSupplier = () -> this .applicationContext .getBean (beanName );
146+ return new EndpointBean (this .applicationContext .getEnvironment (), beanName , beanType , beanSupplier );
145147 }
146148
147149 private void addExtensionBeans (Collection <EndpointBean > endpointBeans ) {
@@ -159,8 +161,9 @@ private void addExtensionBeans(Collection<EndpointBean> endpointBeans) {
159161 }
160162
161163 private ExtensionBean createExtensionBean (String beanName ) {
162- Object bean = this .applicationContext .getBean (beanName );
163- return new ExtensionBean (this .applicationContext .getEnvironment (), beanName , bean );
164+ Class <?> beanType = ClassUtils .getUserClass (this .applicationContext .getType (beanName ));
165+ Supplier <Object > beanSupplier = () -> this .applicationContext .getBean (beanName );
166+ return new ExtensionBean (this .applicationContext .getEnvironment (), beanName , beanType , beanSupplier );
164167 }
165168
166169 private void addExtensionBean (EndpointBean endpointBean , ExtensionBean extensionBean ) {
@@ -233,7 +236,8 @@ private void assertNoDuplicateOperations(EndpointBean endpointBean, MultiValueMa
233236 }
234237
235238 private boolean isExtensionExposed (EndpointBean endpointBean , ExtensionBean extensionBean ) {
236- return isFilterMatch (extensionBean .getFilter (), endpointBean ) && isExtensionExposed (extensionBean .getBean ());
239+ return isFilterMatch (extensionBean .getFilter (), endpointBean )
240+ && isExtensionTypeExposed (extensionBean .getBeanType ());
237241 }
238242
239243 /**
@@ -242,10 +246,21 @@ private boolean isExtensionExposed(EndpointBean endpointBean, ExtensionBean exte
242246 * @param extensionBean the extension bean
243247 * @return {@code true} if the extension is exposed
244248 */
249+ @ Deprecated
245250 protected boolean isExtensionExposed (Object extensionBean ) {
246251 return true ;
247252 }
248253
254+ /**
255+ * Determine if an extension bean should be exposed. Subclasses can override this
256+ * method to provide additional logic.
257+ * @param extensionBeanType the extension bean type
258+ * @return {@code true} if the extension is exposed
259+ */
260+ protected boolean isExtensionTypeExposed (Class <?> extensionBeanType ) {
261+ return true ;
262+ }
263+
249264 private boolean isEndpointExposed (EndpointBean endpointBean ) {
250265 return isFilterMatch (endpointBean .getFilter (), endpointBean ) && !isEndpointFiltered (endpointBean )
251266 && isEndpointExposed (endpointBean .getBean ());
@@ -257,10 +272,21 @@ private boolean isEndpointExposed(EndpointBean endpointBean) {
257272 * @param endpointBean the endpoint bean
258273 * @return {@code true} if the endpoint is exposed
259274 */
275+ @ Deprecated
260276 protected boolean isEndpointExposed (Object endpointBean ) {
261277 return true ;
262278 }
263279
280+ /**
281+ * Determine if an endpoint bean should be exposed. Subclasses can override this
282+ * method to provide additional logic.
283+ * @param beanType the endpoint bean type
284+ * @return {@code true} if the endpoint is exposed
285+ */
286+ protected boolean isEndpointTypeExposed (Class <?> beanType ) {
287+ return true ;
288+ }
289+
264290 private boolean isEndpointFiltered (EndpointBean endpointBean ) {
265291 for (EndpointFilter <E > filter : this .filters ) {
266292 if (!isFilterMatch (filter , endpointBean )) {
@@ -272,7 +298,7 @@ private boolean isEndpointFiltered(EndpointBean endpointBean) {
272298
273299 @ SuppressWarnings ("unchecked" )
274300 private boolean isFilterMatch (Class <?> filter , EndpointBean endpointBean ) {
275- if (!isEndpointExposed (endpointBean .getBean ())) {
301+ if (!isEndpointTypeExposed (endpointBean .getBeanType ())) {
276302 return false ;
277303 }
278304 if (filter == null ) {
@@ -392,7 +418,9 @@ private static class EndpointBean {
392418
393419 private final String beanName ;
394420
395- private final Object bean ;
421+ private final Class <?> beanType ;
422+
423+ private final Supplier <Object > beanSupplier ;
396424
397425 private final EndpointId id ;
398426
@@ -402,17 +430,18 @@ private static class EndpointBean {
402430
403431 private Set <ExtensionBean > extensions = new LinkedHashSet <>();
404432
405- EndpointBean (Environment environment , String beanName , Object bean ) {
406- MergedAnnotation <Endpoint > annotation = MergedAnnotations
407- .from ( bean . getClass (), SearchStrategy . TYPE_HIERARCHY ). get (Endpoint .class );
433+ EndpointBean (Environment environment , String beanName , Class <?> beanType , Supplier < Object > beanSupplier ) {
434+ MergedAnnotation <Endpoint > annotation = MergedAnnotations . from ( beanType , SearchStrategy . TYPE_HIERARCHY )
435+ .get (Endpoint .class );
408436 String id = annotation .getString ("id" );
409437 Assert .state (StringUtils .hasText (id ),
410- () -> "No @Endpoint id attribute specified for " + bean . getClass () .getName ());
438+ () -> "No @Endpoint id attribute specified for " + beanType .getName ());
411439 this .beanName = beanName ;
412- this .bean = bean ;
440+ this .beanType = beanType ;
441+ this .beanSupplier = beanSupplier ;
413442 this .id = EndpointId .of (environment , id );
414443 this .enabledByDefault = annotation .getBoolean ("enableByDefault" );
415- this .filter = getFilter (this . bean . getClass () );
444+ this .filter = getFilter (beanType );
416445 }
417446
418447 void addExtension (ExtensionBean extensionBean ) {
@@ -432,8 +461,12 @@ String getBeanName() {
432461 return this .beanName ;
433462 }
434463
464+ Class <?> getBeanType () {
465+ return this .beanType ;
466+ }
467+
435468 Object getBean () {
436- return this .bean ;
469+ return this .beanSupplier . get () ;
437470 }
438471
439472 EndpointId getId () {
@@ -457,17 +490,20 @@ private static class ExtensionBean {
457490
458491 private final String beanName ;
459492
460- private final Object bean ;
493+ private final Class <?> beanType ;
494+
495+ private final Supplier <Object > beanSupplier ;
461496
462497 private final EndpointId endpointId ;
463498
464499 private final Class <?> filter ;
465500
466- ExtensionBean (Environment environment , String beanName , Object bean ) {
467- this .bean = bean ;
501+ ExtensionBean (Environment environment , String beanName , Class <?> beanType , Supplier <Object > beanSupplier ) {
468502 this .beanName = beanName ;
503+ this .beanType = beanType ;
504+ this .beanSupplier = beanSupplier ;
469505 MergedAnnotation <EndpointExtension > extensionAnnotation = MergedAnnotations
470- .from (bean . getClass () , SearchStrategy .TYPE_HIERARCHY ).get (EndpointExtension .class );
506+ .from (beanType , SearchStrategy .TYPE_HIERARCHY ).get (EndpointExtension .class );
471507 Class <?> endpointType = extensionAnnotation .getClass ("endpoint" );
472508 MergedAnnotation <Endpoint > endpointAnnotation = MergedAnnotations
473509 .from (endpointType , SearchStrategy .TYPE_HIERARCHY ).get (Endpoint .class );
@@ -481,8 +517,12 @@ String getBeanName() {
481517 return this .beanName ;
482518 }
483519
520+ Class <?> getBeanType () {
521+ return this .beanType ;
522+ }
523+
484524 Object getBean () {
485- return this .bean ;
525+ return this .beanSupplier . get () ;
486526 }
487527
488528 EndpointId getEndpointId () {
0 commit comments