كيف تتم إعادة توطيد حبوب الربيع المفردة عند إلغاء التسلط

StackOverflow https://stackoverflow.com/questions/3471835

سؤال

أريد أن أعيد تبعيات Singleton التي تم سكانها إلى حبوب الربيع النموذجية ، بعد أن تم هجرها.

قل أنني حصلت على حبة عملية ، والتي تعتمد على فول مستودع. فاصوليا المستودع هو النطاق كفرد ، لكن فول العملية عبارة عن نموذج أولي. بشكل دوري أقوم بتسلسل العملية ، ثم تخلصها لاحقًا.

class Process {
   private Repository repository;
   // getters, setters, etc.
}

لا أريد أن أقوم بتسلسل المستودع. كما أنني لا أريد أن أضع "عابرة" على متغير العضو الذي يحمل إشارة إليه قيد التنفيذ ، ولا إشارة إلى نوع من الوكيل ، أو أي شيء آخر غير متغير عضو قديم عادي تم الإعلان عنه كمستودع.

ما أعتقد أنني أريده هو أن تملأ العملية اعتمادها بوكيل قابل للتسلسل والذي يشير (مع مرجع عابر) إلى المستودع ، وعند الفتحة ، يمكن أن تجد المستودع مرة أخرى. كيف يمكنني تخصيص الربيع للقيام بذلك؟

أعتقد أنه يمكنني استخدام وكيل للاحتفاظ بمراجع التبعية ، مثلما يشبه إلى حد كبير. أتمنى أن أتمكن من استخدام هذه التقنية الدقيقة. لكن الوكيل الذي رأيته في توليد الربيع ليس قابلاً للتسلسل ، وتقول المستندات إنه إذا استخدمته مع حبة مفردة ، فسوف أحصل على استثناء.

يمكنني استخدام نطاق مخصص ، ربما ، على حبوب المفرد ، من شأنه أن يوفر دائمًا وكيلًا عندما يُطلب منه حبة مخصصة. هل هذه فكرة جيدة؟ أفكار أخرى؟

هل كانت مفيدة؟

المحلول

ماذا عن الإضافة باستخدام الجوانب لإضافة خطوة الحقن عند إلغاء تخصيص الكائن؟

ستحتاج إلى SideJ أو ما شابه ذلك. سيعمل بشكل مشابه جدًا للوظيفة القابلة للتكوين في الربيع.

على سبيل المثال ، أضف بعض النصائح حول طريقة "private void readobject (ObjectInputStream in)

قد تساعد هذه المقالة أيضًا: http://java.sun.com/developer/technicalarticles/programming/serialization/

نصائح أخرى

لقد استخدمت هذا بدلاً من ذلك ، دون أي وكيل:

public class Process implements HttpSessionActivationListener {
    ...
    @Override
    public void sessionDidActivate(HttpSessionEvent e) {
        ServletContext sc = e.getSession().getServletContext();
        WebApplicationContext newContext = WebApplicationContextUtils
            .getRequiredWebApplicationContext(sc);
        newContext.getAutowireCapableBeanFactory().configureBean(this, beanName);
    }
}

المثال هو لبيئة ويب عندما يقوم خادم التطبيق بتسلسل الجلسة ، ولكن يجب أن يعمل مع أي تطبيق ApplicationContext.

يوفر الربيع حلاً لهذه المشكلة.

ألق نظرة على وثائق الربيع http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/aop.html#aop-atconfigable.

7.8.1 باستخدام كائنات المجال لحقن التبعية مع الربيع

...

يهدف الدعم إلى استخدام الكائنات التي تم إنشاؤها خارج التحكم في أي حاوية. غالبًا ما تندرج كائنات المجال في هذه الفئة لأنها غالبًا ما يتم إنشاؤها برمجيًا باستخدام المشغل الجديد ، أو بواسطة أداة ORM نتيجة لاستعلام قاعدة البيانات.

الحيلة هي استخدام نسج وقت التحميل. ما عليك سوى بدء تشغيل JVM مع -javaagent: path/to/org.springframework.instrument- {version} .jar. سيتعرف هذا الوكيل على كل كائن تم إنشاء مثيل له ، وإذا تم شرحه باستخدام configible ، فسيتم تكوينه (enjectowired أو reSource Enperence) هذا الكائن.

فقط قم بتغيير فئة العملية إلى

@Configurable
class Process {

   @Autowired
   private transient Repository repository;
   // getters, setters, etc.
}

كلما قمت بإنشاء مثيل جديد

Process process = new Process();

سوف Spring تلقائيا ضخ التبعيات. هذا يعمل أيضًا إذا كان كائن العملية غير مرغوب فيه.

أعتقد أن فكرة تسلسل الفول ثم إجبارها على إعادة التبعية ليست هي أفضل بنية.

ماذا عن وجود نوع من BERCENTWRAPPER BEAN بدلاً من ذلك والذي يمكن أن يكون مفردة. سيتم حقنه مع المستودع وإما أن يدير إلغاء تخصيص العملية أو يحتوي على مجموعة لذلك. عندما يتم تعيين عملية جديدة في الغلاف ، فإنها ستدعو setRepository() على هذه العملية. يمكن تعيين الفاصوليا التي تستخدم العملية إما مع واحد جديد بواسطة Wrapper أو استدعاء ProcessWrapper الذي من شأنه أن ينفوض العملية.

class ProcessWrapper {
   private Repository repository;
   private Process process;
   // getters, setters, etc.

   public void do() {
      process.do();
   }

   public void setProcess(Process process) {
      this.process = process;
      this.process.setRepository(repository);
   }
}

الإجابة على سؤالي الخاص: كيف قمت بحل المشكلة حتى الآن هو إنشاء فئة أساسية تتسلسل وتمرض باستخدام وكيل صغير رخيص. يحتوي الوكيل على اسم الفول فقط.

ستلاحظ أنه يستخدم عالميًا للوصول إلى سياق الربيع ؛ قد يخزن الحل الأكثر أناقة السياق في متغير محلي مؤشر ترابط ، شيء من هذا القبيل.

public abstract class CheaplySerializableBase 
   implements Serializable, BeanNameAware {

    private String name;

    private static class SerializationProxy implements Serializable {

        private final String name;

        public SerializationProxy(CheaplySerializableBase target) {
            this.name = target.name;
        }

        Object readResolve() throws ObjectStreamException {
            return ContextLoader.globalEvilSpringContext.getBean(name);
        }

    }

    @Override
    public void setBeanName(String name) {
        this.name = name;
    }

    protected Object writeReplace() throws ObjectStreamException {
        if (name != null) {
            return new SerializationProxy(this);
        }
        return this;
    }
}

الكائن التسلسلي الناتج هو 150 بايت أو نحو ذلك (إذا كنت أتذكر بشكل صحيح).

طريقة applicationContext.getAutowireCapableBeanFactory().autowireBean(detachedBean); يمكن استخدام @Autowired تصبح الحقول null). انظر المثال أدناه. يتم حذف تفاصيل التسلسل للبساطة.

public class DefaultFooService implements FooService {

    @Autowired
    private ApplicationContext ctx;

    @Override
    public SerializableBean bar() {
        SerializableBean detachedBean = performAction();
        ctx.getAutowireCapableBeanFactory().autowireBean(detachedBean);
        return detachedBean;
    }

    private SerializableBean performAction() {
        SerializableBean outcome = ... // Obtains a deserialized instance, whose @Autowired fields are detached.
        return outcome;
    }

}


public class SerializableBean {

    @Autowired
    private transient BarService barService;

    private int value;

    public void doSomething() {
        barService.doBar(value);
    }

}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top