重点标识
bean的作用域,简单来说,就是bean起作用的范围,
常见的有:
prototype:也叫原型作用域,每次请求都会获取一个新的bean。
singleton:相当于单例模式,即Ioc容器中只存在一个实例,怎么获取都是它。
不常见的有:
session(会话级别), web项目中比较常见,一般登录后就会产生,然后一直持续到超时或者注销,在这期间,共用一个bean。
request(一次请求创建一个实例),http每次请求都会产生一个新的bean。
applicaton,全局作用域 (与Spring容器进行绑定,一个Spring容器,一个bean,一般作为全局配置,系统初始化时,进行加载,当然在一些特殊的web工程中,是有可能多个Spring容器的,也会存在多个application)。
websocket(消息会话)在整个消息连接期间,共享一个bean,了解到的,一般用于聊天室之类的。
有一些不能直接使用的bean,注入到Spring容器中,我们可以使用工厂bean来搞定,如okhttp;
singleton(单例)
注入Spring容器中,如果不增加额外的说明,一般就是单例的,如下:
public class User {
private String id;
private String username;
private String address;
}
<bean class="org.tongzhou.model.User" id="user" scope="singleton"/>
public static void main(String[] args) {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
Object user = context.getBean("user");
Object user2 = context.getBean("user");
System.out.println(user2 == user);
}
结果之然是true;
如果我们改了scope,则又是另一种结果了。
prototype (多实例)
<bean class="org.tongzhou.model.User" id="user" scope="prototype"/>
调用main方法,结果就是false。
okhttp
我们可以看到,new 一个okhttp是没有set方法,让我们填入参数的,这种情况下,我们又想将这个第三方的工具类交给Spring容器去进行管理,那我们可以这么做。
,
静态工厂
public class OkHttpClientStaticFactory {
private static OkHttpClient client;
static {
OkHttpClient.Builder builder = new OkHttpClient.Builder();
builder.setConnectTimeout$okhttp(10000);
builder.setReadTimeout$okhttp(10000);
client = builder.build();
}
public static OkHttpClient getInstances(){
return client;
}
}
xml配置
这里需要注意的是,这里注入的是OkhttpClient返回的实例而不是OkHttpClientStaticFactory
<bean class="org.tongzhou.factory.OkHttpClientStaticFactory" factory-method="getInstances"/>
测试方法
public static void main(String[] args) {
ClassPathXmlApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
OkHttpClient bean = classPathXmlApplicationContext.getBean(OkHttpClient.class);
Request build = new Request.Builder().get().url("https://www.baidu.com").build();
Call call = bean.newCall(build);
call.enqueue(new Callback() {
/**
* 请求失败的回调
* @param call
* @param e
*/
@Override
public void onFailure(@NotNull Call call, @NotNull IOException e) {
}
/**
* 请求成功的回调
* @param call
* @param response
* @throws IOException
*/
@Override
public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
System.out.println(response.body().string());
}
});
}
实例工厂
创建一个实例,加载的时候调用!
public class OkHttpClientFactory {
OkHttpClient okHttpClient;
public OkHttpClient getOkHttpClient(){
if(okHttpClient == null){
OkHttpClient.Builder builder = new OkHttpClient.Builder();
builder.setConnectTimeout$okhttp(10000);
builder.setReadTimeout$okhttp(10000);
okHttpClient = builder.build();
}
return okHttpClient;
}
}
这里需要注意,必须要取到实例之后,才能调用。
<bean class="org.tongzhou.factory.OkHttpClientFactory" id="clientFactory"/>
<bean id="client" factory-bean="clientFactory" factory-method="getOkHttpClient"/>
public static void main(String[] args) {
ClassPathXmlApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
OkHttpClient bean = classPathXmlApplicationContext.getBean("client",OkHttpClient.class);
FactoryBean(推荐)
实现FactoryBean接口,这里我们可以进去看一下,实际上getObject()方法体,getObjectType() 返回类型,重点是isSingleton(),默认是true,也就是单例,但实际上,如果你返回一个false,他也不一定是prototype ,因为除此之外,还有其他的作用域,这里需要注意下;
ok 我们接下来看代码实现
public class OkHttpClientFactoryBean implements FactoryBean<OkHttpClient> {
@Override
public OkHttpClient getObject() throws Exception {
OkHttpClient.Builder builder = new OkHttpClient.Builder();
builder.setConnectTimeout$okhttp(10000);
builder.setReadTimeout$okhttp(10000);
return builder.build();
}
@Override
public Class<?> getObjectType() {
return OkHttpClient.class;
}
@Override
public boolean isSingleton() {
return true;
}
}
这里要注意,这边注册到spring容器的,是它的getObject方法,如果想要获得它本身,则可以这样获取。
<bean class="org.tongzhou.factory.OkHttpClientFactoryBean" id="client2"/>
public static void main(String[] args) {
ClassPathXmlApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
Object bean = classPathXmlApplicationContext.getBean("client2");
//获得他本身所代表的实例
Object bean2 = classPathXmlApplicationContext.getBean("&client2");
System.out.println(bean);
System.out.println(bean2);
}
``