스프링xxfactory에 관하여.getBeanByType
5884 단어 factory
jstack을 통해 6~700개의 스레드가 모두 막힌 상태임을 알 수 있습니다: BLOCKED
"resin-tcp-connection-*:8080-2401" daemon prio=10 tid=0x00002aab3df66000 nid=0x1693 waiting for monitor entry [0x00002aac50f09000]
java.lang.Thread.State: BLOCKED (on object monitor)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:180)
- waiting to lock <0x00002aaabe5fd790> (a java.util.concurrent.ConcurrentHashMap)
at org.springframework.beans.factory.support.AbstractBeanFactory.isTypeMatch(AbstractBeanFactory.java:415)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanNamesForType(DefaultListableBeanFactory.java:223)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeansOfType(DefaultListableBeanFactory.java:303)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeansOfType(DefaultListableBeanFactory.java:297)
at org.springframework.context.support.AbstractApplicationContext.getBeansOfType(AbstractApplicationContext.java:941)
at org.springframework.beans.factory.BeanFactoryUtils.beansOfTypeIncludingAncestors(BeanFactoryUtils.java:224)
at org.springframework.beans.factory.BeanFactoryUtils.beanOfTypeIncludingAncestors(BeanFactoryUtils.java:309)
구체적인 오류는 위에서 보십시오.spring의 원본 코드를 보았습니다
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
synchronized (this.singletonObjects) {
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null && allowEarlyReference) {
ObjectFactory singletonFactory = (ObjectFactory) this.singletonFactories.get(beanName);
if (singletonFactory != null) {
singletonObject = singletonFactory.getObject();
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
}
}
}
return (singletonObject != NULL_OBJECT ? singletonObject : null);
}
인터넷상에서 이것은 스프링의 결함이지만 최신 버전까지 복구되지 않았다.구체적으로 URL과 같습니다.
https://jira.springsource.org/browse/SPR-6870
스프링에서 스프링 용기 관리를 받는 Bean은 getBeanByName or getBeanByType을 통해
그 중에서 전자에서 얻을 수 있는 beanspring은 캐시를 추가한 것이고, getBeanBy Type은 매번 다시 생성한다. (사실은 나도 그의 원본 코드를 깊이 연구한 적이 없다)
하지만 나는 테스트를 하나 했다.
long startTime = System.currentTimeMillis();
User user3 = null;
for(int i=0; i<100000; i++) {
user3 = BeanFactory.getBean("user");
user3.print();
}
long endTime = System.currentTimeMillis();
System.out.println("getBeanByName spend time :" + (endTime - startTime) + "ms");
System.out.println("current momory:" + SprintTest.getUsedMemory());
User user4 = null;
for(int i=0; i<100000; i++) {
user4 = BeanFactory.getBean(User.class);
user4.print();
}
long end = System.currentTimeMillis();
System.out.println("getBeanBytype spend time :" + (end - endTime) + "ms");
System.out.println("current momory:" + SprintTest.getUsedMemory());
Factory 방법:
@SuppressWarnings("unchecked")
public static <T> T getBean(final String name) {
return (T) ctx.getBean(name);
}
public static <T> T getBean(final Class<T> clazz) {
return clazz.cast(BeanFactoryUtils.beanOfTypeIncludingAncestors(ctx, clazz));
}
결과는 다음과 같습니다.
getBeanByName spend time :86ms
current momory:899560
getBeanBytype spend time :773ms
current momory:1576440
충격적이야...시간은 수량급의 차이이고 공간도 큰 차이가 있다.
get Bean By Type을 최대한 적게 사용하도록 권장합니다. 꼭 필요하면 인위적인 캐시를 추가해서 이런 성능 문제를 해결할 수 있습니다. 이런 버그가 발생하지 않도록 최대한 적게 사용하세요.
그 밖에 또 다른 문제를 제기했다. 어떤 학우들은 Util에서 Sprint 관리의 종류를 인용했다. 보통 Util의 방법은 정적이다. 그 자체가 Sprint 용기의 관리 범위 안에 있지 않다. 그러면 어떻게 이 방법을 해결할 수 있겠는가. Sprng 공장으로 bean을 얻을 수 있다.
public class BeanFactory implements ApplicationContextAware {
private static ApplicationContext ctx;
private static BeanFactory singleton;
public BeanFactory() {
singleton = this;
}
public static BeanFactory getInstance(){
return singleton;
}
public void setApplicationContext(ApplicationContext ctx)
throws BeansException {
BeanFactory.ctx = ctx;
}
@Autowired
private User user;
public User getUser() {
return user;
}
@SuppressWarnings("unchecked")
public static <T> T getBean(final String name) {
return (T) ctx.getBean(name);
}
public static <T> T getBean(final Class<T> clazz) {
return clazz.cast(BeanFactoryUtils.beanOfTypeIncludingAncestors(ctx, clazz));
}
BeanFactory를 통해 가능합니다.getInstance().getBean("name")의 방법으로 이루어집니다.
Spring에서 관리하는 bean에서 다른 bean을 호출하면 간단하거나 Spring의 @Autowired를 통해 주입하거나 set를 통해 주입해도 됩니다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
CXFf 클라이언트는 서버에 의존하고 서버에 의존하지 않는 두 가지 실현 방식참고: 서버에 의존하지 않을 때, 인터페이스의 구현 클래스는 @WebService에 테이블 공간을 추가해야 합니다. 그렇지 않으면 이상이 발생합니다. org.apache.cxf.common.i18n.Unchecked...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.