Added FAQ on using BeanPostProcessor to customize namespace-created beans.

This commit is contained in:
Luke Taylor 2010-05-24 17:01:55 +01:00
parent e156d5339a
commit 01308f8308
1 changed files with 49 additions and 2 deletions

View File

@ -598,6 +598,53 @@
configuration in this case. You should also consult the Javadoc for the
relevant classes and interfaces. </para></answer>
</qandaentry>
<qandaentry xml:id="faq-namespace-post-processor">
<question><para>I want to modify the property of a bean that is created by the namespace, but there is
nothing in the schema to support it. What can I do short of abandoning namespace use?</para></question>
<answer>
<para>The namespace functionality is intentionally limited, so it doesn't cover everything that you can
do with plain beans. If you want to do something simple, like modify a bean, or inject a different
dependency, you can do this by adding a <interfacename>BeanPostProcessor</interfacename> to your
configuration. More information can be found in the
<link xlink:href="http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/htmlsingle/spring-framework-reference.html#beans-factory-extension-bpp">Spring Reference Manual</link>.
In order to do this, you need to know a bit about which beans are created, so you should also read the
blog article in the above question on <link xlink:href="#faq-namespace-to-bean-mapping">how the
namespace maps to Spring beans</link>.
</para>
<para>
Normally, you would add the functionality you require to the <methodname>postProcessBeforeInitialization</methodname>
method of <interfacename>BeanPostProcessor</interfacename>. Let's say that you want to customize the
<interfacename>AuthenticationDetailsSource</interfacename> used by the <classname>UsernamePasswordAuthenticationFilter</classname>,
(created by the <literal>form-login</literal> element). You want to extract a particular header called
<literal>CUSTOM_HEADER</literal>from the request and make use of it while authenticating the user.
The processor class would look like this:
<programlisting language="java"><![CDATA[
public class BeanPostProcessor implements BeanPostProcessor {
public Object postProcessAfterInitialization(Object bean, String name) {
if (bean instanceof UsernamePasswordAuthenticationFilter) {
System.out.println("********* Post-processing " + name);
((UsernamePasswordAuthenticationFilter)bean).setAuthenticationDetailsSource(
new AuthenticationDetailsSource() {
public Object buildDetails(Object context) {
return ((HttpServletRequest)context).getHeader("CUSTOM_HEADER");
}
});
}
return bean;
}
public Object postProcessBeforeInitialization(Object bean, String name) {
return bean;
}
}
]]></programlisting>
You would then register this bean in your application context. Spring will automatically invoke it on the
beans defined in the application context.
</para>
</answer>
</qandaentry>
</qandadiv>
</qandaset>
</section>