Проблемы с производительностью при использовании большого количества запросов AOP фасоль с крышкой

Я работаю над полу-большим приложением, использующим Spring 3, и у меня возникают проблемы с производительностью, когда к нему одновременно обращаются сотни пользователей. Я использую несколько bean-компонентов с ограниченным объемом запроса, используя прокси-сервер Spring AOP, и я вижу, что каждый раз, когда я вызываю какой-либо метод одного из этих bean-компонентов, вызывается перехватчик CGLIB, который затем вызывает AbstractBeanFactory.getBean (), который вызывает add () для Синхронизированный набор существующих компонентов Spring. Поскольку этот add () синхронизирован, он эффективно блокирует сервер, когда есть тысячи вызовов, ожидающих добавления в тот же список.

Есть ли способ обойти это с помощью bean-компонентов с ограниченным объемом запроса? Я читал в документации Spring, что CGLIB не используется, если bean-компонент реализует какой-либо интерфейс (http://static.springsource.org/spring/docs/2.0.0/reference/aop.html#d0e9015), но мой запрос ограничивает beans все реализуют одно (фактически одно и то же), и это все еще происходит. И мне определенно нужно, чтобы bean-компоненты имели область действия запроса, потому что некоторые из их полей вычисляются в одной части приложения для конкретного запроса, а затем я использую SpEL, чтобы получить их значение в другой части приложения во время того же запроса. Думаю, если бы я сделал прототип bean-компонентов ограниченным, у меня был бы свежий объект, когда я использовал бы SpEL для их получения во второй раз.

Вот пример кода, который иллюстрирует мою проблему. См. В последних двух строках комментарии, описывающие, где именно у меня возникают проблемы.

<!-- Spring config -->
<bean name="someBean" class="some.custom.class.SomeClass" scope="request">
    <property name="property1" value="value1"/>
    <property name="property2" value="value2"/>
    <aop:scoped-proxy/>
</bean>

<bean name="executingClass" class="some.other.custom.class.ExecutingClass" scope="singleton">
    <property name="myBean" ref="someBean" />
</bean>


public Interface SomeInterface {
    public String getProperty1();
    public void setProperty1(String property);
    public String getProperty2();
    public void setProperty2(String property);
}

public class SomeClass implements SomeInterface {
    private String property1;
    private String property2;

    public String getProperty1() { return propery1; }
    public void setProperty1(String property) { property1=property;}

    public String getProperty2() { return propery2; }
    public void setProperty2(String property) { property2=property;}
}


public class ExecutingClass {
    private SomeInterface myBean;

    public void execute() {
        String property = myBean.getProperty1(); // CGLIB interceptor is invoked here, registering myBean as a bean
        String otherProperty = myBean.getProperty2(); // CGLIB interceptor is invoked here too!  Seems like this is unnecessary. And it's killing my app.
    }
}

У меня одна из следующих идей:

  • Могу ли я сделать запрос Spring Bean с заданной областью действия без проксирования каждого вызова метода, сделанного для bean-компонента? И без пометки каждого метода как «final»?

или ...

  • Могу ли я переопределить фабрику bean-компонентов Spring, чтобы реализовать кэш Bean, который будет проверять, кэширован ли компонент перед вызовом AbstractBeanFactory.getBean ()? И если да, то где мне настроить Spring для использования моей фабрики пользовательских компонентов?
9
задан Cameron 27 January 2011 в 06:43
поделиться