इस सवाल का जवाब देने के बाद से वसंत की दुनिया में बहुत कुछ बदल गया है। स्प्रिंग ने एक नियंत्रक में वर्तमान उपयोगकर्ता को प्राप्त करना आसान बना दिया है। अन्य सेम के लिए, स्प्रिंग ने लेखक के सुझावों को अपनाया और '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
}
}
और, इंटरफ़ेस के डिकूपिंग का एक बिंदु होने के कारण, यूनिट परीक्षण सीधा है। इस उदाहरण में मैं मॉकिटो का उपयोग करता हूं:
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);
}
}
और, अंत में, उत्पादन वसंत विन्यास इस तरह दिखता है:
<bean id="myController" class="com.foo.FooController">
...
<constructor-arg index="1">
<bean class="com.foo.SecurityContextHolderFacade">
</constructor-arg>
</bean>
यह थोड़ा मूर्खतापूर्ण से अधिक लगता है कि स्प्रिंग, सभी चीजों के एक निर्भरता इंजेक्शन कंटेनर, ने कुछ इसी तरह के इंजेक्शन लगाने का तरीका नहीं दिया है। मैं समझता हूं कि मुझे SecurityContextHolder
एसेगी से विरासत में मिला था, लेकिन फिर भी। बात यह है, वे इतने करीब हैं - यदि केवल SecurityContextHolder
अंतर्निहित SecurityContextHolderStrategy
उदाहरण (जो एक इंटरफ़ेस है) प्राप्त करने के लिए एक गेटर था , तो आप उसे इंजेक्ट कर सकते हैं। वास्तव में, मैंने उस प्रभाव के लिए एक जीरा मुद्दा भी खोला ।
एक आखिरी बात - मैंने अभी पहले जो उत्तर दिया था, उसे काफी हद तक बदल दिया है। इतिहास की जाँच करें अगर आप उत्सुक हैं, लेकिन जैसा कि एक सहकर्मी ने मुझे बताया, मेरा पिछला उत्तर बहु-सूत्रीय वातावरण में काम नहीं करेगा। अंतर्निहित SecurityContextHolderStrategy
द्वारा इस्तेमाल किया SecurityContextHolder
, डिफ़ॉल्ट, की एक आवृत्ति ThreadLocalSecurityContextHolderStrategy
है, जो भंडार SecurityContext
एक में ThreadLocal
। इसलिए, SecurityContext
शुरुआती समय में सीधे बीन में इंजेक्शन लगाने के लिए यह एक अच्छा विचार नहीं है - इसे ThreadLocal
बहु-थ्रेडेड वातावरण में, प्रत्येक बार से पुनर्प्राप्त करने की आवश्यकता हो सकती है, इसलिए सही एक को पुनः प्राप्त किया जा सकता है।