Declarando Spring Bean en contexto padre vs contexto infantil

Tengo un objeto spring bean (dao) que instancia en mi ServletContext a través del siguiente xml:

<bean id="userDao" class="com.company.dao.impl.UserDaoImpl">
    <property name="sessionFactory" ref="sessionFactory" />
</bean>

Este bean se declara dentro de mi archivo webapp-servlet.xml y mi aplicación lo utiliza dentro del ServletContext.

También estoy usando SpringSecurity. Tengo entendido que esto se ejecuta en un contexto diferente (el SecurityContext).

Mi aplicación tiene un webapp-security.xml donde instancia un proveedor de autenticación personalizado. Me gustaría usar mi dao que se usa en mi aplicación para hacer también la búsqueda de usuarios en mi contexto de seguridad, pero cuando ejecuto:

<bean id="userAuthenticationProvider" class="com.company.security.UserAuthenticationProvider">
    <property name="userDao" ref="userDao" />
</bean>

Recibo errores que dicen que no existe ese bean "userDao". El bean está conectado automáticamente en beans declarados en mi otro contexto, pero no dentro de mi contexto de seguridad. Según Spring Docs, creo que se necesitan ambos contextos separados en web.xml

<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener
    </listener-class>
</listener>

<listener>
    <listener-class>
        org.springframework.security.web.session.HttpSessionEventPublisher
    </listener-class>
</listener>

Así que mi pregunta es, ¿cómo puedo obtener acceso a mi DAO que vive en mi ServletContext dentro de mi SecurityContext? ¿Hay un modificador de alcance para mi dao, o podría obtener de alguna manera el ServletContext en tiempo de ejecución dentro de mi proveedor de autenticación? Como referencia, así es como quiero usarlo dentro de mi proveedor de autenticación:

public class UserAuthenticationProvider extends
    AbstractUserDetailsAuthenticationProvider {

    @Override
protected UserDetails retrieveUser(String userName,
        UsernamePasswordAuthenticationToken authenticationToken)
        throws AuthenticationException {

    // use dao here

gracias por explicarme esto

ACTUALIZAR

Continuando mi investigación, parece que el DispatcherServlet donde estoy usando mis datos es un contexto secundario, y el contexto de seguridad está en algún lugar más arriba. En consecuencia, los beans en mi DispatcherServlet no pueden ser vistos por contextos principales. Creo que la respuesta es mover mis declaraciones de bean al contexto de la aplicación principal de alguna manera, pero no estoy seguro de cómo hacerlo. Aquí está mi web.xml

<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>WEB-INF/spring-*.xml
    </param-value>
</context-param>

<listener>
    <listener-class>
        org.springframework.security.web.session.HttpSessionEventPublisher
    </listener-class>
</listener>

<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener
    </listener-class>
</listener>

<filter>
    <filter-name>springSecurityFilterChain</filter-name>
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy
    </filter-class>
</filter>

<filter-mapping>
    <filter-name>springSecurityFilterChain</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

<servlet>
    <servlet-name>myapp</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet
    </servlet-class>
    <load-on-startup>1</load-on-startup>
    <init-param>
        <param-name>listings</param-name>
        <param-value>true</param-value>
    </init-param>
</servlet>

    ...

Moví toda mi creación de dao a spring-dao.xml, y en spring-security.xml ahora estoy haciendo un:

<import resource="spring-dao.xml" />

Sin embargo, los datos aún permanecen visibles para el contexto DispatcherServlet e invisibles para mi SecurityContext.

RESPONDIDO

De acuerdo, lo descubrí. Aquí hay algunos enlaces útiles:

http: //static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/beans.html#context-creat

http: //forum.springsource.org/showthread.php? 115774-Spring-Security-Custom-UserDetailsService-to-use-User-Service-Dao

http: //static.springsource.org/spring-security/site/faq.html#faq-method-security-in-web-contex

Así que el problema era que debíamos asegurarnos de que el dao existe en el ApplicationContext (contenedor de resorte superior). Para asegurarme de que esto sucedió, cambié mi web.xml para que sea:

<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>WEB-INF/spring-dao.xml WEB-INF/spring-security.xml
    </param-value>
</context-param>

<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener
    </listener-class>
</listener>

<listener>
    <listener-class>
        org.springframework.security.web.session.HttpSessionEventPublisher
    </listener-class>
</listener>

<filter>
    <filter-name>springSecurityFilterChain</filter-name>
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy
    </filter-class>
</filter>

<filter-mapping>
    <filter-name>springSecurityFilterChain</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

<servlet>
    <servlet-name>webapp</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet
    </servlet-class>
    <load-on-startup>1</load-on-startup>
    <init-param>
        <param-name>listings</param-name>
        <param-value>true</param-value>
    </init-param>
</servlet>

Pensé que esto aseguraría que el primer cargador de contexto que se inicia leerá mi configuración de dao (y creará mis beans de dao), luego mi configuración de seguridad. Dado que los beans dao se crean de esta forma, eliminé la declaración anterior "import resource =" spring-dao.xml "" en security.xml porque ya no será necesaria.

Justo después de esa configuración de parámetros de contexto, creé el ContextLoaderListener. Este es un contenedor de resorte de nivel superior que el DispatcherServlet, por lo que pensé que poner esto primero sería el primer tipo en leer esas configuraciones, archivos yé luego crearía los frijoles. Entonces, cualquier contexto secundario tendría acceso a ellos. Puede que no sea así como funciona, ya que DispatcherServlet puede que ni siquiera lea el contextConfigLocation, pero incluso si lo hace, pensé que en este punto los beans ya estarían declarados, por lo que el contexto padre los posee.

Ahora, para otro truco ... para obtener mi DAO, podrían @Autowired. Tuve que inyectarlo manualmente a través de XML:

    <bean id="userAuthenticationProvider" class="com.company.app.security.UserAuthenticationProvider">
    <property name="userDao" ref="userDao" />
</bean>

Por supuesto, hice los métodos getter y setter en mi dao, ¡y listo! No sé por qué el @Autowired no funciona aquí. Supongo que es por diseño. Quizás esto sea particular del SecurityContext (no se extraerá de otros contextos), o quizás @Autowired en generalsolament extrae del contexto actual, o tal vez porque creé el bean a través de XML, ¿también tengo que establecer las propiedades a través de xml y no a través de anotaciones? (las anotaciones están habilitadas y funcionan en el espacio de nombres de mi aplicación de nivel superior).

De todas formas ... todavía no entiendo mucho, pero lo importante es que finalmente está funcionando.

Respuestas a la pregunta(1)

Su respuesta a la pregunta