2009-05-06 3 views
10

나는 주입이 필요한 필드에 Spring의 @Configurable annotation w/@Resource를 통해 자동 의존성 주입을 사용하려고한다. 이것은 JVM에 spring-agent.jar를 전달하는 것과 같은 몇 가지 설정과 관련이 있습니다. 전체 내용은 see here입니다.왜 Spring의 @Configurable은 때때로 작동하며 때로는 그렇지 않습니까?

주로 작동합니다. Tomcat이 부팅 될 때 AspectJ 초기화 메시지가 나타나고 User 객체는 FileService 참조를 자동으로 가져옵니다.

가끔 문제가 발생하는 경우가 있습니다. 완전히 무작위로 보인다. 때로는 부팅을하고 의존성을 주입하지 않으며 때로는 의존성을 주입하지도합니다. 이전에 @Transactional이 사용자에게 문제가 발생했기 때문에 충돌이 발생했기 때문에 프록시로 믿습니다. 나는 JPA를 사용하고있어서, 나의 사용자는 @Entity로 표시되어있다. 그래서 가장 좋은 추측은 이것이 충돌을 일으킨다는 것이다. 프록시 자동 프록시를 사용할 수 없다는 것을 읽었습니다. 충돌을 상쇄하기 위해 나는 온라인에서 찾은 몇 가지 노트를 따라 갔다. CGLIB하이버 네이트 (내 JPA impl)가 사용하는 javassist을 제외했다.

단서 :

  • 그것은 전부 또는 아무것도입니다. 모든 @Configurable 인스턴스가 삽입되었거나 삽입되지 않았습니다.
  • DB에서 엔터티를 다시로드 (reinstantiating)해도 도움이되지 않습니다. 그것은 작동하거나하지 않습니다.
  • 톰캣을 재부팅해도 몇 번이라도 문제가 해결되지 않습니다. 거푸집을 다시 굴리는 것만이 재배치입니다. 즉, 재배포하면 작동 할 수 있습니다.

어떻게 될 수 있습니까? @Configurable을 JPA와 함께 사용하는 사람이 있습니까? 왜 dependencyCheck = true 종속성이 실제로 주입되지 않을 때 오류가 발생합니까?

엔티티

@Entity 
@Configurable(dependencyCheck = true) 
@NamedQueries({ @NamedQuery(name = "User.findAll", query = "SELECT user FROM User user"), 
    @NamedQuery(name = "User.findByEmail", query = "SELECT user FROM User user WHERE user.email = :email") }) 
public abstract class User extends BaseModel { 

private static final long serialVersionUID = 7881431079061750040L; 

@Id 
@GeneratedValue(strategy = GenerationType.TABLE) 
private Long id; 

@Column(unique = true, nullable = false) 
private String email; 

@Basic(optional = false) 
private String password; 

@Resource 
private transient UserEmailer userEmailer; 

@Resource 
private transient FileService fileService; 

... 

aop.xml

<!DOCTYPE aspectj PUBLIC 
    "-//AspectJ//DTD//EN" "http://www.eclipse.org/aspectj/dtd/aspectj.dtd"> 
<aspectj> 
    <weaver options="-verbose"> 
     <include within="com.myapp.domain..*" /> 
     <exclude within="*..*CGLIB*" /> 
     <exclude within="*..*javassist*" /> 
    </weaver> 
    <aspects> 
     <aspect name="org.springframework.beans.factory.aspectj.AbstractInterfaceDrivenDependencyInjectionAspect" /> 
    </aspects> 
</aspectj> 

applicationContext.xml

... 

<context:spring-configured /> 

<context:load-time-weaver /> 

<context:component-scan base-package="com.myapp" /> 

... 
+1

@Configurable 및 @Transactional과 관련된 이러한 유형의 문제도 발생했습니다. 오래 동안, 스프링 컨텍스트가 초기화되기 전에 클래스 로더가 클래스 로딩과 관련이 있다고 생각합니다.이 스레드를보십시오 : http://forum.springsource.org/showthread.php?t=68406. 이 버그는 매우 귀찮습니다. – ghempton

+1

스프링에 대한 모든 변경 사항을 고려하면이 문제에 대한 더 나은 해결책이 있습니까? – Snekse

답변

1

때 사출 아무튼 어떤 이유로 든 코드가 종속성 검사를 수행 할 방법이 없으므로 오류가 발생했습니다.

그렇지 않으면 임의의 오류를 나타내는 여기에 아무것도 표시되지 않습니다. 확인할 간단한 예제를 추출 할 수 있습니까?

+0

안녕하세요. 의견을 보내 주셔서 감사 드리며, 집에 돌아 왔을 때 간단한 예제를 사용하겠습니다. 왜냐하면 나는 spring-agent.jar를 작은 범위의 TomcatInstrumentableClassLoader로 바꾸기 때문에 (6.8.4.6.2 절 참조) Spring 참조 문서의 Tomcat ent. 이상하게도이 변화는 발생하는 문제의 빈도를 낮추는 것으로 보이지만 완전히 고쳐지지는 않습니다. – rcampbell

+0

@Configurable을 @Component보다 많이 사용하는 이유는 무엇입니까? –

+0

문서에 따르면 그들은 여기에서 동일한 것을 수행 할 것입니다. 스프링 관리 빈에서 DI 주입을 위해 @Component를 사용하고, 비 스프링 관리 빈에서 DI 주입을 위해 @Config를 사용합니다. 그래서 그들은 둘 다 작동하지만 콩의 스프링 상태에 대한 힌트를 얻기 위해 다른 것들을 사용합니다. – rcampbell

2

명백한 점을 발견 할 수 없으므로 제안 사항 - 컴파일 타임 짜기를 사용해 보았습니까? 개발 중에는 좀 더 번거로운 일이있을 수 있지만 런타임에서 일관된 결과를 얻길 바랍니다.

+0

프로덕션 배포를 위해 컴파일 타임을 사용하는 것이 좋습니다. 또한 aspect-j 위버 JDK 매개 변수 설정을 잊어 버리는 것과 관련된 문제를 방지합니다. . . . 컴파일 타임 짜기는 통합 테스트에 적합합니다. –

1

배포 프로세스가 의심스러운 것으로 들립니다. 작동하는 배포를 수행 한 다음 해당 배포를 디렉토리에 복사 할 수 있습니까? 그런 다음 작동하지 않는 것을 얻을 때까지 다른 배포를 수행하십시오. (어느 순서로든) 그런 다음 마지막으로 두 가지 배포 디렉토리 구조 및 파일을 비교하고 차이점이 있는지 비교할 수있는 비교 도구를 사용하십시오.

행운을 빈다. 생산성을 떨어 뜨리기 위해 겉으로보기에는 임의의 문제를 좋아하지 않는다.

+1

그건 내가 결코 고려하지 않은 정말 좋은 생각이야. 나는 오늘 밤 그것을 시험해 볼 것이다. BTW, @Configurable을 사용하여 생산성을 높이기 시작한 것은 재미 있습니다. 특정 지점 (예 : 공장, Repo 등)에서 수동 DI를 수행하기 전에 도메인 객체가 인스턴스화되었지만 결코 주입되지 않은 부재중 영역을 추적했습니다. 지금 당장 @Cofig가 우아함에 +1, orig 솔루션에 비해 생산성이 -1이라고 말하고 싶습니다. – rcampbell

+0

그래, 지금 나는 새로운 기술을 사용하고있는 프로젝트에있다. 그들은 당신이 고비를 넘을 때까지 생산성을 거의 향상시키지 않습니다. 나는 봄의 주석 속성에 직면하려고 시도조차하지 못했다. 너무 많은 새로운 것들, 그리고 XML은 매번 작동합니다. –

3

먼저 자원, 서비스 또는 다른 bean을 종속성으로 데이터 모델 클래스에 주입하는 것은 좋지 않다고해야합니다. 그러나 그것은 디자인의 문제입니다.

@Configurable의 사용법에서는 웹 응용 프로그램, 필터 또는 서블릿의 사용자 정의 태그와 같은 Spring 컨텍스트 외부에서 객체가 인스턴스화되는 경우에이 방법을 사용했습니다. 내가 그들을 사용하려고 시도하는 첫 번째 방법은 당신처럼로드 시간 짜기로했습니다. 그다지 잘 작동했지만 디버깅이 더 이상 작동하지 않는 동안 핫 코드 배포와 같은 몇 가지 단점이있었습니다.

나는 또한 정확히 당신이 설명하는 문제를 경험했기 때문에 나는 로딩 시간에서 컴파일 시간으로 전환하기로 결정했다. 그래서 나는 Eclipse에 AJDT plugin을 설치하고 Spring의 aspecjt 지원을 사용했다. 그게 내 문제를 해결해 줬어.

+0

토마스에게 감사드립니다. 나는 왜 내가 여기 이런 방식으로 설계했는지에 대한 설명을 가지고있다 : http://stackoverflow.com/questions/694374/how-can-i-resolve-the-conflict-between-loose-coupling-dependency-injection-and-a 기본적으로 나에게 영향을주는 도메인 중심 디자인이됩니다. 내 도메인 모델은 단지 데이터였습니다. 그들은 주로 테이블 행을 나타 냈습니다.이 좋은 책을 읽은 후에는 OOP/data + behavior, 루트 엔티티가 자식 엔티티를 담당하는 등으로 이동하기로 결정했습니다.이 예제를 사용하는 좋은 예는 하위 엔티티에 Spring-wired Factory를 주입하는 것입니다 그의 부모님 께. – rcampbell

+0

"매우 좋은 책"을 의미합니까? 재미있는 소리 ... –

+0

이 책은 에릭 에반스의 도메인 기반 디자인입니다. 필자는 마틴 파울러 (Martin Fowler)가 엔터프라이즈 응용 프로그램 아키텍처의 패턴 (Patterns of Enterprise Application Architecture)에서 추천 한 또 다른 훌륭한 책입니다. – rcampbell

3

내게는 봄에 잘 알려진 버그가있는 것처럼 들립니다 : http://jira.springframework.org/browse/SPR-5401.

여러 응용 프로그램 컨텍스트에서 구성 가능을 사용할 수 있습니까? 이 경우에는 그 중 하나만 종속성 주입의 대상이됩니다. 어떤 애플리케이션이로드 될지는 마지막 애플리케이션 컨텍스트에 따라 결정됩니다.

해결책? 없음 :-(이 문제를 해결할 계획은 없습니다. 적어도 SpringSource 사람이 4 월에 독일에서 열린 JAX 컨퍼런스에서 말한 것입니다.

관련 문제