যেমনটি আমরা জানি স্প্রিং কার্যকারিতা যুক্ত করতে প্রক্সি ব্যবহার করে ( @Transactional
এবং @Scheduled
উদাহরণস্বরূপ)। দুটি বিকল্প রয়েছে - একটি জেডিকে ডায়নামিক প্রক্সি ব্যবহার করে (ক্লাসটি নন-খালি ইন্টারফেস প্রয়োগ করতে পারে), বা সিজিএলআইবি কোড জেনারেটর ব্যবহার করে একটি শিশু শ্রেণি তৈরি করা। আমি সর্বদা ভেবেছিলাম যে প্রক্সিমোড আমাকে জেডিকে ডায়নামিক প্রক্সি এবং সিজিএলআইবির মধ্যে নির্বাচন করতে দেয়।
তবে আমি একটি উদাহরণ তৈরি করতে সক্ষম হয়েছিল যা দেখায় যে আমার অনুমানটি ভুল:
মামলা 1:
একক:
@Service
public class MyBeanA {
@Autowired
private MyBeanB myBeanB;
public void foo() {
System.out.println(myBeanB.getCounter());
}
public MyBeanB getMyBeanB() {
return myBeanB;
}
}
প্রোটোটাইপ:
@Service
@Scope(value = "prototype")
public class MyBeanB {
private static final AtomicLong COUNTER = new AtomicLong(0);
private Long index;
public MyBeanB() {
index = COUNTER.getAndIncrement();
System.out.println("constructor invocation:" + index);
}
@Transactional // just to force Spring to create a proxy
public long getCounter() {
return index;
}
}
প্রধান:
MyBeanA beanA = context.getBean(MyBeanA.class);
beanA.foo();
beanA.foo();
MyBeanB myBeanB = beanA.getMyBeanB();
System.out.println("counter: " + myBeanB.getCounter() + ", class=" + myBeanB.getClass());
আউটপুট:
constructor invocation:0
0
0
counter: 0, class=class test.pack.MyBeanB$$EnhancerBySpringCGLIB$$2f3d648e
এখানে আমরা দুটি জিনিস দেখতে পারি:
MyBeanB
শুধুমাত্র একবার ইনস্ট্যান্ট করা হয়েছিল ।- এর
@Transactional
কার্যকারিতা যুক্ত করতেMyBeanB
, বসন্ত সিজিএলবি ব্যবহার করেছে।
কেস 2:
আমাকে MyBeanB
সংজ্ঞাটি সংশোধন করতে দিন :
@Service
@Scope(value = "prototype", proxyMode = ScopedProxyMode.TARGET_CLASS)
public class MyBeanB {
এই ক্ষেত্রে আউটপুট হয়:
constructor invocation:0
0
constructor invocation:1
1
constructor invocation:2
counter: 2, class=class test.pack.MyBeanB$$EnhancerBySpringCGLIB$$b06d71f2
এখানে আমরা দুটি জিনিস দেখতে পারি:
MyBeanB
3 বার ইনস্ট্যান্ট করা হয়েছিল- এর
@Transactional
কার্যকারিতা যুক্ত করতেMyBeanB
, বসন্ত সিজিএলবি ব্যবহার করেছে।
আপনি কি বলতে পারেন যে কি চলছে? প্রক্সি মোডটি আসলে কীভাবে কাজ করে?
পুনশ্চ
আমি ডকুমেন্টেশন পড়েছি:
/**
* Specifies whether a component should be configured as a scoped proxy
* and if so, whether the proxy should be interface-based or subclass-based.
* <p>Defaults to {@link ScopedProxyMode#DEFAULT}, which typically indicates
* that no scoped proxy should be created unless a different default
* has been configured at the component-scan instruction level.
* <p>Analogous to {@code <aop:scoped-proxy/>} support in Spring XML.
* @see ScopedProxyMode
*/
তবে এটি আমার পক্ষে পরিষ্কার নয়।
হালনাগাদ
কেস 3:
আমি আরও একটি মামলা তদন্ত করেছি, যার মধ্যে থেকে আমি ইন্টারফেসটি বের করেছি MyBeanB
:
public interface MyBeanBInterface {
long getCounter();
}
@Service
public class MyBeanA {
@Autowired
private MyBeanBInterface myBeanB;
@Service
@Scope(value = "prototype", proxyMode = ScopedProxyMode.INTERFACES)
public class MyBeanB implements MyBeanBInterface {
এবং এই ক্ষেত্রে আউটপুট হয়:
constructor invocation:0
0
constructor invocation:1
1
constructor invocation:2
counter: 2, class=class com.sun.proxy.$Proxy92
এখানে আমরা দুটি জিনিস দেখতে পারি:
MyBeanB
3 বার ইনস্ট্যান্ট করা হয়েছিল- এর
@Transactional
কার্যকারিতা যুক্ত করতেMyBeanB
, স্প্রিং একটি জেডিকে ডায়নামিক প্রক্সি ব্যবহার করেছিল।
MyBeanB
ক্লাসটি কোনও ইন্টারফেস প্রসারিত করে না, তাই অবাক হওয়ার কিছু নেই যে আপনার কনসোল লগটি সিজিএলআইবি প্রক্সি উদাহরণগুলি দেখায়। ক্ষেত্রে 3 আপনি একটি ইন্টারফেস প্রবর্তন এবং প্রয়োগ করে, ফলস্বরূপ আপনি একটি জেডিকে প্রক্সি পাবেন। এমনকি আপনি আপনার প্রবর্তনীয় পাঠ্যে এটি বর্ণনা করে।
<aop:config proxy-target-class="true">
বা মাধ্যমে কনফিগার করা @EnableAspectJAutoProxy(proxyTargetClass = true)
হয়েছে।