Skip to content

Commit

Permalink
Minor refinements along the way of researching static CGLIB callbacks
Browse files Browse the repository at this point in the history
Specifically, our CallbackFilter doesn't hold an implicit reference to the containing ConfigurationClassEnhancer class anymore.

Issue: SPR-10307
  • Loading branch information
jhoeller authored and unknown committed Mar 13, 2013
1 parent b00f90f commit fffeaee
Showing 1 changed file with 43 additions and 33 deletions.
@@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2012 the original author or authors. * Copyright 2002-2013 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -52,25 +52,13 @@ class ConfigurationClassEnhancer {


private static final Log logger = LogFactory.getLog(ConfigurationClassEnhancer.class); private static final Log logger = LogFactory.getLog(ConfigurationClassEnhancer.class);


private static final Class<?>[] CALLBACK_TYPES = {BeanMethodInterceptor.class, private static final CallbackFilter CALLBACK_FILTER = new ConfigurationClassCallbackFilter();
DisposableBeanMethodInterceptor.class, NoOp.class};

private static final CallbackFilter CALLBACK_FILTER = new CallbackFilter() {
public int accept(Method candidateMethod) {
// Set up the callback filter to return the index of the BeanMethodInterceptor when
// handling a @Bean-annotated method; otherwise, return index of the NoOp callback.
if (BeanAnnotationHelper.isBeanAnnotated(candidateMethod)) {
return 0;
}
if (DisposableBeanMethodInterceptor.isDestroyMethod(candidateMethod)) {
return 1;
}
return 2;
}
};


private static final Callback DISPOSABLE_BEAN_METHOD_INTERCEPTOR = new DisposableBeanMethodInterceptor(); private static final Callback DISPOSABLE_BEAN_METHOD_INTERCEPTOR = new DisposableBeanMethodInterceptor();


private static final Class<?>[] CALLBACK_TYPES =
{BeanMethodInterceptor.class, DisposableBeanMethodInterceptor.class, NoOp.class};

private final Callback[] callbackInstances; private final Callback[] callbackInstances;




Expand Down Expand Up @@ -109,21 +97,6 @@ public Class<?> enhance(Class<?> configClass) {
return enhancedClass; return enhancedClass;
} }


/**
* Marker interface to be implemented by all @Configuration CGLIB subclasses.
* Facilitates idempotent behavior for {@link ConfigurationClassEnhancer#enhance(Class)}
* through checking to see if candidate classes are already assignable to it, e.g.
* have already been enhanced.
* <p>Also extends {@link DisposableBean}, as all enhanced
* {@code @Configuration} classes must de-register static CGLIB callbacks on
* destruction, which is handled by the (private) {@code DisposableBeanMethodInterceptor}.
* <p>Note that this interface is intended for framework-internal use only, however
* must remain public in order to allow access to subclasses generated from other
* packages (i.e. user code).
*/
public interface EnhancedConfiguration extends DisposableBean {
}

/** /**
* Creates a new CGLIB {@link Enhancer} instance. * Creates a new CGLIB {@link Enhancer} instance.
*/ */
Expand All @@ -149,6 +122,43 @@ private Class<?> createClass(Enhancer enhancer) {
} }





/**
* Marker interface to be implemented by all @Configuration CGLIB subclasses.
* Facilitates idempotent behavior for {@link ConfigurationClassEnhancer#enhance(Class)}
* through checking to see if candidate classes are already assignable to it, e.g.
* have already been enhanced.
* <p>Also extends {@link DisposableBean}, as all enhanced
* {@code @Configuration} classes must de-register static CGLIB callbacks on
* destruction, which is handled by the (private) {@code DisposableBeanMethodInterceptor}.
* <p>Note that this interface is intended for framework-internal use only, however
* must remain public in order to allow access to subclasses generated from other
* packages (i.e. user code).
*/
public interface EnhancedConfiguration extends DisposableBean {
}


/**
* CGLIB CallbackFilter implementation that points to BeanMethodInterceptor and
* DisposableBeanMethodInterceptor.
*/
private static class ConfigurationClassCallbackFilter implements CallbackFilter {

public int accept(Method candidateMethod) {
// Set up the callback filter to return the index of the BeanMethodInterceptor when
// handling a @Bean-annotated method; otherwise, return index of the NoOp callback.
if (BeanAnnotationHelper.isBeanAnnotated(candidateMethod)) {
return 0;
}
if (DisposableBeanMethodInterceptor.isDestroyMethod(candidateMethod)) {
return 1;
}
return 2;
}
}


/** /**
* Intercepts calls to {@link FactoryBean#getObject()}, delegating to calling * Intercepts calls to {@link FactoryBean#getObject()}, delegating to calling
* {@link BeanFactory#getBean(String)} in order to respect caching / scoping. * {@link BeanFactory#getBean(String)} in order to respect caching / scoping.
Expand All @@ -175,7 +185,7 @@ public Object intercept(Object obj, Method method, Object[] args, MethodProxy pr
/** /**
* Intercepts the invocation of any {@link DisposableBean#destroy()} on @Configuration * Intercepts the invocation of any {@link DisposableBean#destroy()} on @Configuration
* class instances for the purpose of de-registering CGLIB callbacks. This helps avoid * class instances for the purpose of de-registering CGLIB callbacks. This helps avoid
* garbage collection issues See SPR-7901. * garbage collection issues. See SPR-7901.
* @see EnhancedConfiguration * @see EnhancedConfiguration
*/ */
private static class DisposableBeanMethodInterceptor implements MethodInterceptor { private static class DisposableBeanMethodInterceptor implements MethodInterceptor {
Expand Down

0 comments on commit fffeaee

Please sign in to comment.