[SPRING] Spring 애플리케이션 컨텍스트에 사전 구성된 Bean 추가하기
SPRINGSpring 애플리케이션 컨텍스트에 사전 구성된 Bean 추가하기
다음 메소드를 구현하는 클래스를 작성 중입니다.
public void run(javax.sql.DataSource dataSource);
이 메서드 내에서 다음과 비슷한 구성 파일을 사용하여 Spring 응용 프로그램 컨텍스트를 구성하고자합니다.
<bean id="dataSource" abstract="true" />
<bean id="dao" class="my.Dao">
<property name="dataSource" ref="dataSource" />
</bean>
"dataSource"bean이 환경 설정 파일에서 참조되는 곳이라면 Spring이 내 메소드에 전달 된 DataSource 객체를 사용하도록 강제 할 수 있습니까?
해결법
-
==============================
1.나는 똑같은 상황에 처해 있었다. 아무도 내 솔루션을 제안하지 않았기 때문에 (그리고 제 솔루션이 더 우아하다고 생각합니다), 저는 그것을 미래 세대를 위해 여기에 추가 할 것입니다 :-)
나는 똑같은 상황에 처해 있었다. 아무도 내 솔루션을 제안하지 않았기 때문에 (그리고 제 솔루션이 더 우아하다고 생각합니다), 저는 그것을 미래 세대를 위해 여기에 추가 할 것입니다 :-)
솔루션은 두 단계로 구성됩니다.
1 단계:
//create parent BeanFactory DefaultListableBeanFactory parentBeanFactory = new DefaultListableBeanFactory(); //register your pre-fabricated object in it parentBeanFactory.registerSingleton("dataSource", dataSource); //wrap BeanFactory inside ApplicationContext GenericApplicationContext parentContext = new GenericApplicationContext(parentBeanFactory); parentContext.refresh(); //as suggested "itzgeoff", to overcome a warning about events
2 단계:
//create your "child" ApplicationContext that contains the beans from "beans.xml" //note that we are passing previously made parent ApplicationContext as parent ApplicationContext context = new ClassPathXmlApplicationContext( new String[] {"beans.xml"}, parentContext);
-
==============================
2.두 개의 Spring 인터페이스가 필요한 것을 구현하는 데 사용될 수 있다는 것을 발견했습니다. BeanNameAware 인터페이스를 사용하면 Spring은 setBeanName (String) 메소드를 호출하여 애플리케이션 컨텍스트 내에서 오브젝트의 이름을 알릴 수있다. FactoryBean 인터페이스는 Spring에게 객체 자체를 사용하지 말고, getObject () 메소드가 호출 될 때 리턴 된 객체를 알려줍니다. 함께 모으면 다음과 같이됩니다.
두 개의 Spring 인터페이스가 필요한 것을 구현하는 데 사용될 수 있다는 것을 발견했습니다. BeanNameAware 인터페이스를 사용하면 Spring은 setBeanName (String) 메소드를 호출하여 애플리케이션 컨텍스트 내에서 오브젝트의 이름을 알릴 수있다. FactoryBean 인터페이스는 Spring에게 객체 자체를 사용하지 말고, getObject () 메소드가 호출 될 때 리턴 된 객체를 알려줍니다. 함께 모으면 다음과 같이됩니다.
public class PlaceholderBean implements BeanNameAware, FactoryBean { public static Map<String, Object> beansByName = new HashMap<String, Object>(); private String beanName; @Override public void setBeanName(String beanName) { this.beanName = beanName; } @Override public Object getObject() { return beansByName.get(beanName); } @Override public Class<?> getObjectType() { return beansByName.get(beanName).getClass(); } @Override public boolean isSingleton() { return true; } }
이제 Bean 정의가 다음과 같이 축소되었습니다.
<bean id="dataSource" class="PlaceholderBean" />
자리 표시자는 응용 프로그램 컨텍스트를 만들기 전에 값을받습니다.
public void run(DataSource externalDataSource) { PlaceholderBean.beansByName.put("dataSource", externalDataSource); ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml"); assert externalDataSource == context.getBean("dataSource"); }
상황이 성공적으로 작동하는 것 같습니다!
-
==============================
3.두 번째 솔루션은 새로 고침 문제로 인해 예외가 발생합니다. 보다 우아한 방법은 컨텍스트에 개체를 추가 한 다음 xmlreader를 사용하여 xml 정의를로드하는 것입니다. 그러므로:
두 번째 솔루션은 새로 고침 문제로 인해 예외가 발생합니다. 보다 우아한 방법은 컨텍스트에 개체를 추가 한 다음 xmlreader를 사용하여 xml 정의를로드하는 것입니다. 그러므로:
ObjectToBeAddedDynamically objectInst = new ObjectToBeAddedDynamically(); DefaultListableBeanFactory parentBeanFactory = new DefaultListableBeanFactory(); parentBeanFactory.registerSingleton("parameterObject", objectInst); GenericApplicationContext parentContext = new GenericApplicationContext(parentBeanFactory); XmlBeanDefinitionReader xmlReader = new XmlBeanDefinitionReader(parentContext); xmlReader.loadBeanDefinitions(new FileSystemResource("beandefinitions.xml")); parentContext.refresh(); ObjectUsingDynamicallyAddedObject userObjectInst= (ObjectUsingDynamicallyAddedObject )parentContext.getBean("userObject");
과
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="userObject" class="com.beanwiring.ObjectUsingDynamicallyAddedObject" > <constructor-arg ref="parameterObject" /> </bean> </beans>
완벽하게 작동합니다!
-
==============================
4.포함 된 DataSource에 단순히 위임하는 DataSource에 대한 래퍼 클래스를 만들 수 있습니다.
포함 된 DataSource에 단순히 위임하는 DataSource에 대한 래퍼 클래스를 만들 수 있습니다.
public class DataSourceWrapper implements DataSource { DataSource dataSource; public void setDataSource(DataSource dataSource) { this.dataSource = dataSource; } @Override public Connection getConnection() throws SQLException { return dataSource.getConnection(); } @Override public Connection getConnection(String username, String password) throws SQLException { return dataSource.getConnection(username, password); } //delegate to all the other DataSource methods }
그런 다음 Spring 컨텍스트 파일에서 DataSourceWrapper를 선언하고 모든 빈에 연결합니다. 그런 다음 메서드에서 DataSourceWrapper에 대한 참조를 가져온 다음 래핑 된 DataSource를 메서드에 전달 된 것으로 설정합니다.
이 모든 작업은로드 될 때 Spring 컨텍스트 파일에서 일어나는 일에 크게 의존합니다. Bean이 컨텍스트가로드 될 때 BeanFactoryPostProcessor를 작성해야하는 경우 BeanFactoryPostProcessor를 작성하여로드 할 때 Spring 컨텍스트 파일을 변경하는 대신 BeanFactoryPostProcessor를 작성해야 할 수도 있습니다 (로드가 끝나면 Lazy-init이이 문제를 해결할 수도 있음). ).
-
==============================
5."new"를 호출하여 객체를 생성하면 Spring factory의 제어를받지 않습니다.
"new"를 호출하여 객체를 생성하면 Spring factory의 제어를받지 않습니다.
Spring이 DataSource를 run ()에 전달하는 대신 객체에 삽입하는 것이 어떻습니까?
-
==============================
6.외부 XML 파일을 사용하여 파일 시스템 리소스로로드 한 다음 응용 프로그램 컨텍스트에 구성된 빈을 주입하는보다 우아한 방법이 있습니다. 그러므로:
외부 XML 파일을 사용하여 파일 시스템 리소스로로드 한 다음 응용 프로그램 컨텍스트에 구성된 빈을 주입하는보다 우아한 방법이 있습니다. 그러므로:
import org.springframework.beans.BeansException; import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.support.BeanDefinitionRegistry; import org.springframework.beans.factory.xml.XmlBeanDefinitionReader; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.context.support.GenericApplicationContext; import org.springframework.core.annotation.Order; import org.springframework.core.io.FileSystemResource; import org.springframework.stereotype.Service; @Service @Order(-100) public class XmlBeanInitializationService implements ApplicationContextAware, InitializingBean { private ApplicationContext applicationContext; @Value("${xmlConfigFileLocation}") private String xmlConfigFileLocation; @Override public void afterPropertiesSet() throws Exception { XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader((BeanDefinitionRegistry)applicationContext); reader.loadBeanDefinitions(new FileSystemResource(xmlConfigFileLocation)); } @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { this.applicationContext = applicationContext; } }
여기서 $ {xmlConfigFileLocation}은 application.properties 파일에 지정된 속성으로 시스템의 파일 위치를 가리 킵니다.
xmlConfigFileLocation="your-file-path-anywhere-in-your-system"
xml 파일에는 다음 항목이 포함될 수 있습니다.
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean class="com.yourpackage.YourBean1Class"></bean> <bean class="com.yourpackage.YourBean2Class"></bean> <bean class="com.yourpackage.YourBean3Class"></bean> </beans>
따라서 애플리케이션이 스프링을 시작하면 클래스를로드하고 애플리케이션 컨텍스트에 Bean을로드한다.
희망이 사람을 도움이됩니다.
from https://stackoverflow.com/questions/496711/adding-a-pre-constructed-bean-to-a-spring-application-context by cc-by-sa and MIT license
'SPRING' 카테고리의 다른 글
[SPRING] 스프링 보안으로 세션 ID 검색하기 (0) | 2019.03.04 |
---|---|
[SPRING] 스프링 빈을 동적으로 주입 (0) | 2019.03.04 |
[SPRING] 봄 - 트랜잭션 읽기 전용 (0) | 2019.03.04 |
[SPRING] MongoRepository에서 일부 HTTP 메소드를 내보내는 것을 방지하려면 어떻게해야합니까? (0) | 2019.03.04 |
[SPRING] spring xml 설정에 환경 변수를 주입하는 방법은 무엇입니까? (0) | 2019.03.04 |