এই প্রশ্নের উত্তর দেওয়া হওয়ার পরে বসন্ত বিশ্বে অনেক কিছুই পরিবর্তিত হয়েছে। স্প্রিং বর্তমান ব্যবহারকারীকে একটি নিয়ামক হিসাবে পাওয়া সহজ করেছে। অন্যান্য মটরশুটির জন্য, বসন্ত লেখকের পরামর্শ গ্রহণ করেছে এবং 'সিকিউরিটি কনটেক্সটহোল্ডার' এর ইনজেকশনটিকে সহজ করেছে। আরও বিস্তারিত মন্তব্য করা হয়।
এই সমাধানটি আমি শেষ করে শেষ করেছি। 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প্রতিটি সময় থেকে বহু-থ্রেডযুক্ত পরিবেশে পুনরুদ্ধার করা প্রয়োজন, তাই সঠিকটি পুনরুদ্ধার করা হবে।