Spring框架提供了Spring bean的作用域。
我们可以使用spring范围控制插入Spring bean的各种依赖关系和配置值。
Spring支持以下六个范围。 在基于Web的应用程序中可以使用六个中的四个:
范围 | 描述 |
辛格尔顿 | 它是Spring框架中的默认范围。 对于每个Spring IOC容器,将仅创建Bean的单个实例。 |
原型 | 每当从上下文请求bean时,每次都会创建一个新实例。 |
请求 | Bean范围到HttpServlet Request。 对于每个新请求,将创建一个新的bean实例。该实例仅适用于基于Web的应用程序。 |
届会 | 将bean定义的作用域限定为Http会话,对于每个新会话,将返回该bean的新实例,仅在可识别Web的Spring应用程序上下文中有效。 |
应用 | 将Bean定义的作用域限定为ServletContext。 仅在可感知网络的Spring应用程序上下文中有效。 |
网络插座 | 将bean定义的范围限定在WebSocket会话的生命周期内。 仅在可感知网络的Spring应用程序上下文中有效。 |
Spring Framework提供了用于创建新范围的接口。
1.将Bean视为依赖项
假设beanA具有单例作用域,而beanB具有原型作用域。 假设beanA具有beanB依赖性。 然后,无需使用任何其他配置,它就提供了随机行为,因为beanA将具有该容器的单个实例,但是beanB将不会具有相同的行为。 每当从容器请求beanB时,都会创建一个新实例。
为了解决这些类型的问题, Java spring框架提供了称为代理bean的概念。
对于范围小于父级的依赖项,框架将创建代理而不是创建实际对象。 这些代理将扩展原始对象。
每当beanB中的方法被调用时,内部都会在代理对象上调用它,而不是在实际对象上调用它。 代理将尝试根据作用域从上下文获取对象,并将对其调用原始方法。
例如,SingletonScopedBean,PrototypeScopedBean是分别具有默认作用域和原型作用域的两个bean。
public class SingletonScopedBean{
private PrototypeScopedBean prototypeScopedBean; public String getState(){return this.prototypeScopedBean.getState();}
}
Public class PrototypeScopedBean{private final String state;
public String getState() {return state;}
public void setState() {this.state = UUID.randomUUID().toString();
}
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:aop="http://www.springframework.org/schema/aop"xsi:schemaLocation="http://www.springframework.org/schema/beanshttps://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/aophttps://www.springframework.org/schema/aop/spring-aop.xsd">
<bean id=”prototypeScopedBean” class=”org.example. PrototypeScopedBean” scope=”prototype” >
<aop:scoped-proxy/>
</bean>
<bean id=”singletonScopedBean” class=”org.example. SingletonScopedBean”>
<property name=”prototypeScopedBean” ref=”prototypeScopedBean”>
</bean>
</beans>
这将为prototypeScopedBean创建代理bean,并将代理作为依赖项附加到singletonScopedBean。
每当在prototypeScopedBean bean上调用getState()方法时,它将在proxy上调用该方法,并且proxy将解析prototypeScopedBean实例,并在已解析的对象上调用getState()方法。
2.可以通过两种方式创建代理
- 基于JDK的代理
- 基于CGLIB(动态代理)的代理。
为了创建基于JDK的代理,必须在一个接口上实现该类。
对于基于CGLIB的代理,不存在此限制。
我们可以使用proxy-target-class属性指定代理类型。 如果值为true,则将创建CGLIB代理。 如果该值为false,它将尝试创建基于JDK的代理。
注释方法: Spring框架提供@Scope注释以指定范围。 proxyMode是用于指定代理类型的注释属性。
@Component
@Scope(value="prototype", proxyMode=ScopedProxyMode.TARGET_CLASS)
public class PrototypeScopedBean{private final String state;
public String getState() {return state;}
public void setState() {this.state = UUID.randomUUID().toString();
}
}
@Component
public class SingletonScopedBean{@Autowired private PrototypeScopedBean prototypeScopedBean;public String getState(){return this.prototypeScopedBean.getState();}
}
通过上述更改,SingletonScopedBean将具有PrototypeScopedBean bean类型作为代理。
3. Spring的作用域代理-结论
我们学习了Spring bean作用域,以及如何在bean依赖项中注入各种作用域。 我们还学习了不同类型的代理模式。
翻译自: https://www.javacodegeeks.com/scoped-proxy-in-spring-framework.html