스피링 factory-method 질문입니다

1,349 views
Skip to first unread message

쿠이

unread,
Mar 1, 2013, 11:13:52 PM3/1/13
to ks...@googlegroups.com
안녕하세요. 가입하고 첫글을 질문으로 남깁니다.

현재 스프링에서 간단하게 유틸 클래스를 싱글톤으로 만들고 싶어서 만들어봤는데 오류가 나서 질문입니다.

applicationContext-bean.xml 에는
<bean id="stringUtil" class="com.cooi.common.string.StringUtil" factory-method="getInstance" />

이렇게 선언하고  소스 ㅅ코드는 

       private static final StringUtil stringUtil = new StringUtil();
private StringUtil() {}
public static StringUtil getInstance() {
return stringUtil;
}

이렇게 작성하였습니다. 그런다음 테스트 코드에서

@Autowired
private StringUtil stringUtil;

@Test
public void testIsNull() {
assertTrue("공백을 가진 String", stringUtil.isNull(""));
assertTrue("null을 가진 String", stringUtil.isNull(null));
}

이렇게 실행하였는데

java.lang.IllegalStateException: Failed to load ApplicationContext
at org.springframework.test.context.TestContext.getApplicationContext(TestContext.java:157)
at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:109)
at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:75)
at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:321)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:211)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:288)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:290)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:231)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:71)
at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:174)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'stringUtil' defined in URL [file:src/main/webapp/WEB-INF/conf/applicationContext-bean.xml]: Initialization of bean failed; nested exception is org.springframework.aop.framework.AopConfigException: Could not generate CGLIB subclass of class [class com.cooi.common.string.StringUtil]: Common causes of this problem include using a final class or a non-visible class; nested exception is java.lang.IllegalArgumentException: No visible constructors in class com.cooi.common.string.StringUtil
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:527)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:294)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:225)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:291)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:585)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:913)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:464)
at org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:103)
at org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:1)
at org.springframework.test.context.support.DelegatingSmartContextLoader.loadContext(DelegatingSmartContextLoader.java:228)
at org.springframework.test.context.TestContext.loadApplicationContext(TestContext.java:124)
at org.springframework.test.context.TestContext.getApplicationContext(TestContext.java:148)
... 24 more
Caused by: org.springframework.aop.framework.AopConfigException: Could not generate CGLIB subclass of class [class com.cooi.common.string.StringUtil]: Common causes of this problem include using a final class or a non-visible class; nested exception is java.lang.IllegalArgumentException: No visible constructors in class com.cooi.common.string.StringUtil
at org.springframework.aop.framework.Cglib2AopProxy.getProxy(Cglib2AopProxy.java:213)
at org.springframework.aop.framework.ProxyFactory.getProxy(ProxyFactory.java:112)
at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.createProxy(AbstractAutoProxyCreator.java:476)
at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.wrapIfNecessary(AbstractAutoProxyCreator.java:362)
at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.postProcessAfterInitialization(AbstractAutoProxyCreator.java:322)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsAfterInitialization(AbstractAutowireCapableBeanFactory.java:407)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1461)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:519)
... 37 more
Caused by: java.lang.IllegalArgumentException: No visible constructors in class com.cooi.common.string.StringUtil
at net.sf.cglib.proxy.Enhancer.filterConstructors(Enhancer.java:531)
at net.sf.cglib.proxy.Enhancer.generateClass(Enhancer.java:448)
at net.sf.cglib.transform.TransformingClassGenerator.generateClass(TransformingClassGenerator.java:33)
at net.sf.cglib.core.DefaultGeneratorStrategy.generate(DefaultGeneratorStrategy.java:25)
at net.sf.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:216)
at net.sf.cglib.proxy.Enhancer.createHelper(Enhancer.java:377)
at net.sf.cglib.proxy.Enhancer.create(Enhancer.java:285)
at org.springframework.aop.framework.Cglib2AopProxy.getProxy(Cglib2AopProxy.java:201)
... 44 more


이렇게 오류가났습니다. 음..구글링을 해봐도 이해가 잘안되서 질문을 올려봅니다ㅜㅜ

namkyu Lee

unread,
Mar 1, 2013, 11:25:03 PM3/1/13
to ks...@googlegroups.com
에러 메시지를 보면 애플리케이션 컨텍스트를 load하면서 에러가 발생하였고, 에러 메시지 중 다음의 로그를 보면 CGLIB proxy 생성 중 StringUtil 클래스가 final 로 선언되었기 때문에 에러가 발생하였다고 나오네요.

Could not generate CGLIB subclass of class [class com.cooi.common.string.StringUtil]: Common causes of this problem include using a final class or a non-visible class

CGLIB 프록시를 이용할 경우에는 꼭 default 생성자이면서 final 클래스로 선언되어 있지 않아야 합니다.
상속을 통해서 프록시 객체를 생성하거든요.

감사합니다. ^^


2013년 3월 2일 토요일 오후 1시 13분 52초 UTC+9, 쿠이 님의 말:

쿠이

unread,
Mar 1, 2013, 11:33:52 PM3/1/13
to ks...@googlegroups.com
안녕하세요. ^^ 
StringUtil에서 생성할때 final을 빼고 테스트코드를 다시 돌려봤는데 똑같은 에러가 발생합니다.

스프링에서 싱글톤을 적용해보려고 저렇게 해봤는데..음 쉽지가 않네요.

편현장

unread,
Mar 1, 2013, 11:35:09 PM3/1/13
to ks...@googlegroups.com
일단 위소스로는 인스턴스 변수로 파이널을 선언한 것으로는 오류를 내지는 않을 것같고 생성자를 public 으로 바꾸시면 될겁니다. 이유는 이남규님이 설명하신것(default 생성자 요구)과 동일합니다.
이남규님이 같은 의도로 말씀하셨지만, 잘못 이해하실 여지도 있을거 같아 첨언합니다 :)


2013년 3월 2일 오후 1:33, 쿠이 <phka...@gmail.com>님의 말:
안녕하세요. ^^ 
StringUtil에서 생성할때 final을 빼고 테스트코드를 다시 돌려봤는데 똑같은 에러가 발생합니다.

스프링에서 싱글톤을 적용해보려고 저렇게 해봤는데..음 쉽지가 않네요.

--
Google 그룹스 'Korea Spring User Group' 그룹에 가입했으므로 본 메일이 전송되었습니다.
이 그룹에서 탈퇴하고 더 이상 이메일을 받지 않으려면 ksug+uns...@googlegroups.com에 이메일을 보내세요.
이 그룹에 게시하려면 ks...@googlegroups.com(으)로 이메일을 보내세요.
http://groups.google.com/group/ksug?hl=ko에서 그룹을 방문하세요.
더 많은 옵션을 보려면 https://groups.google.com/groups/opt_out을(를) 방문하세요.
 
 



--
==========================================================
COMAS  Hyun-Jang, Pyun
Assistent Manager / R&D Div. / Solution Business  Comas, Inc.
(Bangbae-Dong) Nambu beltway 2145, Seocho-Gu, Seoul 137-820, Korea
Tel :  +82-2-3218-6300 
Mobile : +82-10-8565-8071  /  Fax : +82-2-3218-6370
E-mail : ker...@comas.co.krslot...@gmail.com

Mark Sunghun Park

unread,
Mar 3, 2013, 4:57:14 PM3/3/13
to ks...@googlegroups.com
I am not using Spring very much but I know that Spring supports singleton as default. I think you do not need to make your class using that singleton code using Spring container. In your case, I think static method would be enough.

Cheers.

2013/3/2 쿠이 <phka...@gmail.com>
안녕하세요. ^^ 
StringUtil에서 생성할때 final을 빼고 테스트코드를 다시 돌려봤는데 똑같은 에러가 발생합니다.

스프링에서 싱글톤을 적용해보려고 저렇게 해봤는데..음 쉽지가 않네요.

Sanghyuk Jung

unread,
Mar 3, 2013, 6:54:15 PM3/3/13
to ks...@googlegroups.com
위에서 말씀하신데로 핵심에러메시지는 
'No visible constructors in class com.cooi.common.string.StringUtil'

인것 같구요, 

CGLib를 이용한 AOP를 쓰면서 visible한 default 생성자가 없어서 생기는 에러입니다..

StringUtil에 특별히 AOP가 필요하시지 않다면 AOP설정을 걷어내시고 테스트해보시면 되실것 같습니다.. (제  PC에서는 CGLIB를 이용한 AOP가 없을때는  private생성자로 선언해도 잘 됩니다..)


Spring을 쓸때는 클래스에서 직접 singleton 을 구현하실 필요없이(private생성자 + static getInstance 메소드 구현) 일반적인 생성방식을 가진 클래스도 application context에 그냥 bean을 등록하면 같은 효과를 얻을 수 있습니다. 직접 singleton 패턴을 구현하는 방식은 요즘에는 잘 쓰지 않는듯합니다. 

factory-method 선언은 소스를 수정하기가 어려운  레거시코드를 bean등록할 때 주로 많이 썼었습니다..

factory-bean, factory-method 선언을 함께 써서 
 Spring의 FactoryBean와 같은 역할을 스프링에 대한 의존관계없이 구현하는 방법도 factory-method의 한 쓰임새인듯합니다..


2013년 3월 4일 오전 6:57, Mark Sunghun Park <mark.sun...@gmail.com>님의 말:
Reply all
Reply to author
Forward
0 new messages