рд╕реНрдкреНрд░рд┐рдВрдЧ рдмреАрди рдХрд╕реНрдЯрдо рд╕реНрдХреЛрдк

рдореИрдВ рдПрдХ рдЙрджрд╛рд╣рд░рдг рджреЗрдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░реВрдВрдЧрд╛ рдЬрдм рд╕реНрдкреНрд░рд┐рдВрдЧ рдХрд╕реНрдЯрдо рд╕реНрдХреЛрдк рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрдЧреАред



рд╣рдо рдПрдХ рдмреА 2 рдмреА рдФрд░ рдПрд╕рдПрдПрдПрд╕ рдХрдВрдкрдиреА рд╣реИрдВ, рдФрд░ рд╣рдорд╛рд░реЗ рдкреНрд░рддреНрдпреЗрдХ рдХреНрд▓рд╛рдЗрдВрдЯ рдХреЗ рд▓рд┐рдП рдХреБрдЫ рд▓рдВрдмреА рдкреНрд░рдХреНрд░рд┐рдпрд╛рдПрдВ рдЯрд╛рдЗрдорд░ рдкрд░ рдЪрд▓рддреА рд╣реИрдВред

рдкреНрд░рддреНрдпреЗрдХ рдХреНрд▓рд╛рдЗрдВрдЯ рдХреЗ рдкрд╛рд╕ рдХреБрдЫ рдЧреБрдг (рдирд╛рдо, рд╕рджрд╕реНрдпрддрд╛ рдХрд╛ рдкреНрд░рдХрд╛рд░, рдЖрджрд┐) рд╣реИрдВред

рдкрд╣рд▓реЗ, рд╣рдордиреЗ рдЕрдкрдиреА рд╕реЗрд╡рд╛рдУрдВ рдХреЗ рдкреНрд░реЛрдЯреЛрдЯрд╛рдЗрдк рдбрд┐рдмреНрдмреЗ рдмрдирд╛рдП рдФрд░ рдЙрдирдореЗрдВ рд╕реЗ рдкреНрд░рддреНрдпреЗрдХ рдХреЛ рдЧреНрд░рд╛рд╣рдХ рдХреЗ рд╕рднреА рдЖрд╡рд╢реНрдпрдХ рдЧреБрдгреЛрдВ рдФрд░ рдЪрд▓ рд░рд╣реА рдкреНрд░рдХреНрд░рд┐рдпрд╛ (рдкреНрд░рд╡рд╛рд╣ - рдЗрд╕рдХрд╛ рдЕрд░реНрде рд╣реИ рддрд╛рд░реНрдХрд┐рдХ рдкреНрд░рдХреНрд░рд┐рдпрд╛, рдиреМрдХрд░реА, рдУрдПрд╕ рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдирд╣реАрдВ) рдХреЛ рдкрд╛рд░рд┐рдд рдХрд┐рдпрд╛:



@Service @Scope("prototype") public class ServiceA { private Customer customer; private ReloadType reloadType; private ServiceB serviceB; @Autowired private ApplicationContext context; public ServiceA(final Customer customer, final ReloadType reloadType) { this.customer = customer; this.reloadType = reloadType; } @PostConstruct public void init(){ serviceB = (ServiceB) context.getBean("serviceB",customer, reloadType); } public void doSomethingInteresting(){ doSomthingWithCustomer(customer,reloadType); serviceB.doSomethingBoring(); } private void doSomthingWithCustomer(final Customer customer, final ReloadType reloadType) { } }
      
      







 @Service @Scope("prototype") public class ServiceB { private Customer customer; private ReloadType reloadType; public ServiceB(final Customer customer, final ReloadType reloadType) { this.customer = customer; this.reloadType = reloadType; } public void doSomethingBoring(){ } }
      
      







  //... ServiceA serviceA = (ServiceA) context.getBean("serviceA",customer, ReloadType.FullReaload); serviceA.doSomethingInteresting(); //...
      
      







рдпрд╣ рдЕрд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рд╣реИ - рдкрд╣рд▓реЗ, рдЖрдк рдмрд┐рди рдмрдирд╛рддреЗ рд╕рдордп рд╕рдВрдЦреНрдпрд╛ рдпрд╛ рдорд╛рдкрджрдВрдбреЛрдВ рдХреЗ рдкреНрд░рдХрд╛рд░ рдореЗрдВ рдЧрд▓рддреА рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ

рджреВрд╕рд░рд╛ рдмреЙрдпрд▓рд░ рдХреЛрдб рдХрд╛ рдПрдХ рдмрд╣реБрдд



рдЗрд╕рд▓рд┐рдП, рд╣рдордиреЗ рдЕрдкрдиреЗ рджрд╛рдпрд░реЗ рдХреЛ рд╕реЗрдо рдмрдирд╛ рджрд┐рдпрд╛ - "рдЧреНрд░рд╛рд╣рдХ"ред



рдпрд╣ рд╡рд┐рдЪрд╛рд░ рд╣реИ: рдореИрдВ рдПрдХ рдирд┐рд╢реНрдЪрд┐рдд "рд╕рдВрджрд░реНрдн" рдмрдирд╛рддрд╛ рд╣реВрдВ - рдПрдХ рдРрд╕реА рд╡рд╕реНрддреБ рдЬреЛ рдЗрд╕ рдмрд╛рд░реЗ рдореЗрдВ рдЬрд╛рдирдХрд╛рд░реА рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд░рддреА рд╣реИ рдХрд┐ рдХреМрди рд╕реА рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдЕрднреА рдЪрд▓ рд░рд╣реА рд╣реИ (рдХреМрди рд╕рд╛ рдЧреНрд░рд╛рд╣рдХ, рдХрд┐рд╕ рдкреНрд░рдХрд╛рд░ рдХреА рдкреНрд░рдХреНрд░рд┐рдпрд╛ - рдпрд╣ рд╕рднреА рд╕реЗрд╡рд╛рдУрдВ рдХреЛ рдЬрд╛рдирдирд╛ рдЖрд╡рд╢реНрдпрдХ рд╣реИ) рдФрд░ рдЗрд╕реЗ рдереНрд░реЗрдбрд▓реЛрдХ рдореЗрдВ рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд░реЗрдВред

рдЕрдкрдиреЗ рджрд╛рдпрд░реЗ рдХреЗ рд▓рд┐рдП рдмреАрди рдмрдирд╛рддреЗ рд╕рдордп, рдореИрдВ рдЗрд╕ рд╕рдВрджрд░реНрдн рдХреЛ рд╡рд╣рд╛рдВ рдЗрдВрдЬреЗрдХреНрдЯ рдХрд░рддрд╛ рд╣реВрдВред



рдЙрд╕реА рд╕рдВрджрд░реНрдн рдореЗрдВ, рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдмрдирд╛рдИ рдЧрдИ рдмреАрдиреНрд╕ рдХреА рдПрдХ рд╕реВрдЪреА рд╕рдВрдЧреНрд░рд╣реАрдд рдХреА рдЬрд╛рддреА рд╣реИ рддрд╛рдХрд┐ рдкреНрд░рддреНрдпреЗрдХ рдмрд┐рди рдкреВрд░реА рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХреЗ рд▓рд┐рдП рдХреЗрд╡рд▓ рдПрдХ рдмрд╛рд░ рдмрдирд╛рдпрд╛ рдЬрд╛рдПред



рдЬрдм рдкреНрд░рдХреНрд░рд┐рдпрд╛ рд╕рдорд╛рдкреНрдд рд╣реЛ рдЬрд╛рддреА рд╣реИ, рддреЛ рдореИрдВ рдереНрд░реЗрдбрд▓реЛрдХ рдХреЛ рд╕рд╛рдл рдХрд░рддрд╛ рд╣реВрдВ рдФрд░ рд╕рднреА рдмреАрдиреНрд╕ рдХреЛ рдХрдЪрд░рд╛ рдХрд▓реЗрдХреНрдЯрд░ рджреНрд╡рд╛рд░рд╛ рдПрдХрддреНрд░ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред



рдзреНрдпрд╛рди рджреЗрдВ рдХрд┐ рдореЗрд░реЗ рдХрд╛рд░реНрдпрдХреНрд╖реЗрддреНрд░ рдореЗрдВ рд╕рднреА рд╕реЗрдо рдХреЛ рдХреБрдЫ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рд▓рд╛рдЧреВ рдХрд░рдирд╛ рд╣реЛрдЧрд╛ред рдпрд╣ рдХреЗрд╡рд▓ рд╕рдВрджрд░реНрдн рдХреЛ рдЗрдВрдЬреЗрдХреНрдЯ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЖрд╡рд╢реНрдпрдХ рд╣реИред



рддреЛ, xml рдореЗрдВ рд╣рдорд╛рд░реЗ рджрд╛рдпрд░реЗ рдХреА рдШреЛрд╖рдгрд╛ рдХрд░реЗрдВ:



 .. <bean id="customerScope" class="com.scope.CustomerScope"/> <bean class="org.springframework.beans.factory.config.CustomScopeConfigurer"> <property name="scopes"> <map> <entry key="customer" value-ref="customerScope"/> </map> </property> </bean> ...
      
      







рд╣рдо рдЕрдкрдирд╛ рджрд╛рдпрд░рд╛ рд▓рд╛рдЧреВ рдХрд░рддреЗ рд╣реИрдВ:

 public class CustomerScope implements Scope { @Override public Object get(String name, ObjectFactory<?> objectFactory) { CustomerContext context = resolve(); Object result = context.getBean(name); if (result == null) { result = objectFactory.getObject(); ICustomerScopeBean syncScopedBean = (ICustomerScopeBean) result; syncScopedBean.setContext(context); Object oldBean = context.setBean(name, result); if (oldBean != null) { result = oldBean; } } return result; } @Override public Object remove(String name) { CustomerContext context = resolve(); return context.removeBean(name); } protected CustomerContext resolve() { return CustomerContextThreadLocal.getCustomerContext(); } @Override public void registerDestructionCallback(String name, Runnable callback) { } @Override public Object resolveContextualObject(String key) { return null; } @Override public String getConversationId() { return resolve().toString(); } }
      
      







рдЬреИрд╕рд╛ рдХрд┐ рд╣рдо рджреЗрдЦрддреЗ рд╣реИрдВ, рд╕рдорд╛рди рдкреНрд░рдХреНрд░рд┐рдпрд╛ (рдкреНрд░рд╡рд╛рд╣) рдХреЗ рднреАрддрд░ рд╕рдорд╛рди рдмрд┐рди рдЙрджрд╛рд╣рд░рдгреЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ (рдпрд╛рдиреА рдпрд╣ рджрд╛рдпрд░рд╛ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдорд╛рдирдХ рдирд╣реАрдВ рд╣реИ - рдкреНрд░реЛрдЯреЛрдЯрд╛рдЗрдк рдореЗрдВ рд╣рд░ рдмрд╛рд░ рдирдП рдмрдирд╛рдП рдЬрд╛рдПрдВрдЧреЗ, рд╕рд┐рдВрдЧрд▓рдЯрди рдореЗрдВ - рд╡рд╣реА)ред

рдФрд░ рд╕рдВрджрд░реНрдн рд╕реНрд╡рдпрдВ рдереНрд░реЗрдбрд▓реЛрдХ рд╕реЗ рд▓рд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ:



 public class CustomerContextThreadLocal { private static ThreadLocal<CustomerContext> customerContext = new ThreadLocal<>(); public static CustomerContext getCustomerContext() { return customerContext.get(); } public static void setSyncContext(CustomerContext context) { customerContext.set(context); } public static void clear() { customerContext.remove(); } private CustomerContextThreadLocal() { } public static void setSyncContext(Customer customer, ReloadType reloadType) { setSyncContext(new CustomerContext(customer, reloadType)); }
      
      







рдпрд╣ рд╣рдорд╛рд░реЗ рд╕рднреА рдмреАрдиреНрд╕ рдФрд░ рдЗрд╕рдХреЗ рдЕрдореВрд░реНрдд рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреЗ рд▓рд┐рдП рдПрдХ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдмрдирд╛ рд╣реБрдЖ рд╣реИ:

 public interface ICustomerScopeBean { void setContext(CustomerContext context); } public class AbstractCustomerScopeBean implements ICustomerScopeBean { protected Customer customer; protected ReloadType reloadType; @Override public void setContext(final CustomerContext context) { customer = context.getCustomer(); reloadType = context.getReloadType(); } }
      
      







рдФрд░ рдЙрд╕рдХреЗ рдмрд╛рдж, рд╣рдорд╛рд░реА рд╕реЗрд╡рд╛рдПрдВ рдмрд╣реБрдд рдЕрдзрд┐рдХ рд╕реБрдВрджрд░ рд▓рдЧрддреА рд╣реИрдВ:

 @Service @Scope("customer") public class ServiceA extends AbstractCustomerScopeBean { @Autowired private ServiceB serviceB; public void doSomethingInteresting() { doSomthingWithCustomer(customer, reloadType); serviceB.doSomethingBoring(); } private void doSomthingWithCustomer(final Customer customer, final ReloadType reloadType) { } } @Service @Scope("customer") public class ServiceB extends AbstractCustomerScopeBean { public void doSomethingBoring(){ } } //.... CustomerContextThreadLocal.setSyncContext(customer, ReloadType.FullReaload); ServiceA serviceA = context.getBean(ServiceA.class); serviceA.doSomethingInteresting(); //.....
      
      







рд╕рд╡рд╛рд▓ рдЙрда рд╕рдХрддрд╛ рд╣реИ - рд╣рдо рдереНрд░реЗрдбрд▓реЛрдХрд▓ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВ - рд▓реЗрдХрд┐рди рдХреНрдпрд╛ рд╣реЛрдЧрд╛ рдЕрдЧрд░ рд╣рдо рдЕрддреБрд▓реНрдпрдХрд╛рд▓рд┐рдХ рддрд░реАрдХреЛрдВ рдХреЛ рдХрд╣рддреЗ рд╣реИрдВ?

рдореБрдЦреНрдп рдмрд╛рдд рдпрд╣ рд╣реИ рдХрд┐ рдкреВрд░реЗ рдмреАрди рдХрд╛ рдкреЗрдбрд╝ рд╕рдордХрд╛рд▓рд┐рдХ рд░реВрдк рд╕реЗ рдмрдирд╛рдпрд╛ рдЧрдпрд╛ рд╣реИ, рдлрд┐рд░ @Autowired рд╕рд╣реА рдврдВрдЧ рд╕реЗ рдХрд╛рдо рдХрд░реЗрдЧрд╛ред

рдФрд░ рдпрджрд┐ рдХреЛрдИ рднреА рд╡рд┐рдзрд┐ @ Async рд╕реЗ рд╢реБрд░реВ рд╣реЛрддреА рд╣реИ, рддреЛ рдпрд╣ рдбрд░рд╛рд╡рдирд╛ рдирд╣реАрдВ рд╣реИ, рд╕рдм рдХреБрдЫ рдХрд╛рдо рдХрд░реЗрдЧрд╛, рдХреНрдпреЛрдВрдХрд┐ рд╕реЗрдо рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдмрдирд╛рдП рдЧрдП рд╣реИрдВред



рдпрд╣ рд╕рддреНрдпрд╛рдкрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдкрд░реАрдХреНрд╖рдг рд▓рд┐рдЦрдирд╛ рднреА рдЕрдЪреНрдЫрд╛ рд╣реИ рдХрд┐ "рдЧреНрд░рд╛рд╣рдХ" рдЧреБрдВрдЬрд╛рдЗрд╢ рдХреЗ рд╕рд╛рде рд╕рднреА рд╕реЗрдо ICustomerScopeBean рдХреЛ рд▓рд╛рдЧреВ рдХрд░реЗрдВ рдФрд░ рдЗрд╕рдХреЗ рд╡рд┐рдкрд░реАрдд:

  @ContextConfiguration(locations = {"classpath:beans.xml"}, loader = GenericXmlContextLoader.class) @RunWith(SpringJUnit4ClassRunner.class) public class CustomerBeanScopetest { @Autowired private AbstractApplicationContext context; @Test public void testScopeBeans() throws ClassNotFoundException { ConfigurableListableBeanFactory beanFactory = context.getBeanFactory(); String[] beanDefinitionNames = beanFactory.getBeanDefinitionNames(); for (String beanDef : beanDefinitionNames) { BeanDefinition def = beanFactory.getBeanDefinition(beanDef); String scope = def.getScope(); String beanClassName = def.getBeanClassName(); if (beanClassName == null) continue; Class<?> aClass = Class.forName(beanClassName); if (ICustomerScopeBean.class.isAssignableFrom(aClass)) assertTrue(beanClassName + " should have scope 'customer'", scope.equals("customer")); if (scope.equals("customer")) assertTrue(beanClassName + " should implement 'ICustomerScopeBean'", ICustomerScopeBean.class.isAssignableFrom(aClass)); } } }
      
      










All Articles