이 질문에 대한 답을 얻은 후 봄 세계에서 많은 변화가있었습니다. Spring은 컨트롤러에서 현재 사용자를 얻는 것을 단순화했습니다. 다른 빈의 경우 Spring은 저자의 제안을 채택하고 'SecurityContextHolder'의 주입을 단순화했습니다. 자세한 내용은 의견에 있습니다.
이것이 내가 끝낸 해결책입니다. SecurityContextHolder
내 컨트롤러에서 사용하는 대신 SecurityContextHolder
후드에서 사용하지만 코드에서 단일 클래스와 같은 클래스를 추상화 하는 것을 주입하고 싶습니다. 내 인터페이스를 롤링하는 것 외에는 이렇게 할 수있는 방법이 없습니다.
public interface SecurityContextFacade {
SecurityContext getContext();
void setContext(SecurityContext securityContext);
}
이제 내 컨트롤러 (또는 POJO)는 다음과 같습니다.
public class FooController {
private final SecurityContextFacade securityContextFacade;
public FooController(SecurityContextFacade securityContextFacade) {
this.securityContextFacade = securityContextFacade;
}
public void doSomething(){
SecurityContext context = securityContextFacade.getContext();
// do something w/ context
}
}
또한 인터페이스가 디커플링 지점이되기 때문에 단위 테스트가 간단합니다. 이 예에서는 Mockito를 사용합니다.
public class FooControllerTest {
private FooController controller;
private SecurityContextFacade mockSecurityContextFacade;
private SecurityContext mockSecurityContext;
@Before
public void setUp() throws Exception {
mockSecurityContextFacade = mock(SecurityContextFacade.class);
mockSecurityContext = mock(SecurityContext.class);
stub(mockSecurityContextFacade.getContext()).toReturn(mockSecurityContext);
controller = new FooController(mockSecurityContextFacade);
}
@Test
public void testDoSomething() {
controller.doSomething();
verify(mockSecurityContextFacade).getContext();
}
}
인터페이스의 기본 구현은 다음과 같습니다.
public class SecurityContextHolderFacade implements SecurityContextFacade {
public SecurityContext getContext() {
return SecurityContextHolder.getContext();
}
public void setContext(SecurityContext securityContext) {
SecurityContextHolder.setContext(securityContext);
}
}
마지막으로 프로덕션 Spring 구성은 다음과 같습니다.
<bean id="myController" class="com.foo.FooController">
...
<constructor-arg index="1">
<bean class="com.foo.SecurityContextHolderFacade">
</constructor-arg>
</bean>
모든 것의 의존성 주입 컨테이너 인 Spring이 비슷한 것을 주입하는 방법을 제공하지 않았다는 것은 조금 어리석은 것처럼 보입니다. 나는 SecurityContextHolder
acegi에서 상속되었지만 여전히 여전히 이해 합니다. 문제는, 그것들이 너무 가깝다는 것입니다- SecurityContextHolder
기본 SecurityContextHolderStrategy
인스턴스 (인터페이스) 를 얻는 게터 만 있다면 그것을 주입 할 수 있습니다. 사실, 나는 심지어 그 효과에 대한 Jira 문제 를 열었습니다 .
마지막 한 가지-나는 이전에 내가 가진 대답을 크게 바 꾸었습니다. 궁금한 점이 있다면 역사를 확인하십시오.하지만 동료가 지적했듯이 이전 답변은 멀티 스레드 환경에서 작동하지 않습니다. 기본적으로 SecurityContextHolderStrategy
사용되는 SecurityContextHolder
기본은의 인스턴스이며 ThreadLocalSecurityContextHolderStrategy
를에 저장 SecurityContext
합니다 ThreadLocal
. 따라서 SecurityContext
초기화 시간에 Bean에 직접 직접 삽입하는 것이 좋은 아이디어는 아닙니다 ThreadLocal
. 멀티 스레드 환경에서 매번 검색해야 할 수 있으므로 올바른 것을 검색해야합니다.