Supongamos que tengo una clase como se muestra a continuación:
public interface UserDAO { public List<User> list(); } public class UserDAOImpl implements UserDAO { private DataSource dataSource; public UserDAOImpl(DataSource dataSource) { this.dataSource = dataSource; }Supongamos que la configuración de JNDI se realiza correctamente en tomcat.
Ahora, para el mapeo de Spring Bean en muchos sitios, encontré la siguiente configuración:
<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean"> <property name="jndiName" value="java:comp/env/jdbc/UsersDB"/> </bean> <bean id="userDao" class="net.codejava.spring.dao.UserDAOImpl"> <constructor-arg> <ref bean="dataSource" /> </constructor-arg> </bean>Aquí está mi pregunta, la clase UserDAOImpl está buscando el objeto DataSource pero estamos inyectando el objeto JndiObjectFactoryBean [que no es una subclase de DataSource], ya que ni siquiera mencionamos el método de fábrica, ¿cómo o dónde está ocurriendo la conversión?
JndiObjectFactoryBean es un bean de tipo org.springframework.beans.factory.FactoryBean . Estos frijoles se utilizan como una fábrica para exponer un objeto. A continuación se muestran extractos del javadoc para FactoryBean ;
Interfaz para ser implementada por objetos utilizados dentro de BeanFactory, que son en sí mismos fábricas de objetos individuales. Si un bean implementa esta interfaz, se usa como fábrica para exponer un objeto, no directamente como una instancia de bean que se expondrá.
NB: Un bean que implemente esta interfaz no se puede usar como un bean normal. Un FactoryBean se define en un estilo de bean, pero el objeto expuesto para las referencias de bean (getObject()) es siempre el objeto que crea .
FactoryBeans puede admitir singletons y prototipos, y puede crear objetos de forma perezosa bajo demanda o con entusiasmo al inicio. La interfaz SmartFactoryBean permite exponer metadatos de comportamiento más detallados.
Entonces, cuando Spring Framework está conectando automáticamente la fuente de datos para usar DaoImpl, verifica si DataSource es un bean de tipo FactoryBean , que es en este caso, por lo que asignará el objeto del método getObject() de JndiObjectFactoryBean a la fuente de datos. Si desea entender esto mejor, eche un vistazo a los métodos ClassPathXmlApplicationContext.finishBeanfactoryInitialization(..) y DefaultListableBeanFactory.preInstantiateSingletons() que realizan el cableado automático en este caso.
No sé cómo se hace, pero Spring Frameworks sabe que beans es una fábrica de beans DataSource , luego puede inyectar la fuente de datos descubierta en sus otros beans.
Si quieres saber cómo se hace, entonces puedes mirar el código fuente en Spring Framework Github