Spring-02 Bean的作用域和init-method、destroy-method

1、我们先看一下通过spring创建的实例,是单实例的还是多实例的?

UserServlet us1=ioc.getBean("userServlet",UserServlet.class);
UserServlet us2=ioc.getBean("userServlet",UserServlet.class);
System.out.println(us1==us2);//true

通过代码实现,我们发现他是单实例的,默认情况下,spring管理的bean是单实例的

所以,在多线程的情况下,有线程安全问题,你修改了一个bean,会影响其他的bean

//例 单例实的bean 引发的问题       

  public static void main(String[] args) {
                    ClassPathXmlApplicationContext ioc=new ClassPathXmlApplicationContext("applicationContext.xml");
                    
                    UserServlet servlet1=ioc.getBean("userServlet_name", UserServlet.class); 
                    
                    UserInfo  user=new UserInfo();
                    user.setUserName("赵明明");
                    user.setPassword("123");
                    servlet1.user=user;
                    
                    UserServlet servlet2=ioc.getBean("userServlet_name", UserServlet.class); 
                    System.out.println(servlet2.user);  //可以看到,对 servlet1的修改,影响到了servlet2 (实际上它们就是同一个对象)
                    
                    System.out.println(servlet1==servlet2);  //true    
            }
            
            如果是多线程情况下,显然这是有问题的



因此,spring利用作用域,说你想要单例的就给你单例,想要多例的就给你多例的

一、bean的作用域:可以通过配置文件设置,不设置的话就是sigleton的

<bean name="userServlet" class="com.servlet.UserServlet" scope="prototype">
		<property name="userdao" ref="userDaoImpl"></property>
	</bean>

1)sigleton 单例的(默认就是)

2)prototype 多例的

3)request

4)session

如果配置文件改成了scope=prototype上面的单实例的例子创建出来的对象就不是单例的了,而是多实例的

1)sigleton 单例的(默认就是)

对spring管理的bean,默认就是单实例的

这些单实例的bean是什么时候创建的呢?

默认是在容器初始化的时候创建的(容器初始化就是加载配置文件的时候)、

这个创建时间也可以设置(lazy-init="true")、不设置的话就是default,设置为true就是懒加载

  <bean name="userServlet_name" class="com.servlet.UserServlet"  lazy-init="true"  >
                            ...
  </bean>

  经过上面的配置,这个bean不会在容器初始化的时候创建,而是在我们向容器要这个bean的时候才创建 
 如果所有的bean ,都想这样,可以在 beans 标签上加 default-lazy-init="true" ,如下:

<beans default-lazy-init="true"  ...   >

验证一下:真的是在容器加载的时候就创建对象了吗

(1)配置文件:没有配置scope,是单实例的

<bean name="userServlet" class="com.servlet.UserServlet" scope="prototype">
		<property name="userdao" ref="userDaoImpl"></property>
	</bean>

(2)UserServlet中:构造方法

public class UserServlet {
	//依赖对象
	private UserDao userdao;
	public UserServlet() {
		System.out.println("对象创建了");
	}
	
	public void service() {
		userdao.addUser();
		userdao.delUser();
		userdao.updateUser();
		
	}
	public void setUserdao(UserDao userdao) {
		 this.userdao=userdao;
		
	}
	
}

(3)测试文件中:只加载,不调用ioc创建对象

public class Test {
	public static void main(String[] args) {
		
		//spring给我们提供的一个类,这个类能从类路径(src下或者你建的那个文件夹就是源文件夹也叫类路径下)下加载我们的spring的配置文件
		ClassPathXmlApplicationContext ioc=new ClassPathXmlApplicationContext("applicationContext.xml");
		
	}
}

(4)控制台输出结果:我们发现即使没有用Ioc创建对象,也调用了构造方法,这是因为单实例的bean,spring默认在容器加载的时候,就为我们创建好对象

2)prototype 多例的

多实例的自然就没有lazy-init属性了

   在 bean 上加  scope="prototype" 如下:

<bean name="userServlet_name" class="com.servlet.UserServlet" scope="prototype" >
		<property name="dao" ref="userDaoImpl_name" />
 </bean>

思考:什么时候用单实例的bean,什么时候用多实例的bean?

没有线程安全问题的时候,用单实例的,否则用多实例的 
  一般来说, dao层多数用单实例的, 控制层一般用多实例的,但也不是绝对 

如果一个对象的构造方法私有化了?spring还能不能创建出这个对象的实例呢?

可以,即使对象构造方法私有化了,spring也能帮我们创建出这个对象的实例

二、Bean的init-Method和destroy-method方法

单实例的bean中:

(1)UserInfo中

public class UserInfo {
			private int id;
			private String userName;
			private String password;
			private String note;
			...
			
			public void initXXX() {
				System.out.println("initXXX 调用了,主要用于初始化");
			}
			
			public void destoryXXX() {
				System.out.println("destoryXXX 调用了,主要用于清理");
			}	
		}

2)配置文件中只要加上init-method和destroy-method属性

<bean name="userInfo_name" class="com.beans.UserInfo" init-method="initXXX" destroy-method="destoryXXX"> 
		<property name="id" value="1" />
		<property name="userName" value="赵明明" />
		<property name="password" value="123" />
		<property name="note" value="这是spring创建的对象" />
	</bean>

3)测试:

public class Test {
		public static void main(String[] args) {
			ClassPathXmlApplicationContext ioc=new ClassPathXmlApplicationContext("applicationContext.xml");
	
			UserInfo user1=ioc.getBean("userInfo_name", UserInfo.class); 
			UserInfo user2=ioc.getBean("userInfo_name", UserInfo.class); 
			UserInfo user3=ioc.getBean("userInfo_name", UserInfo.class); 
			
			ioc.close();	
		}
	}

4)输出

总结: 

对于单实例的bean,会在创建实例的时候调用init-method,在销毁的时候调用destroy-method

对于多实例的bean,创建的时候每个都会调用init-method,但在销毁的时候,不会调用destroy-method,因为多实例的bean,spring在创建以后,就不再对他们的生命周期负责了

三、集合类型的装配

1、set类型的集合装配,在配置文件中做一个set集合的装配

2、list集合的装配

3、map集合的装配

4、properties :键值对结构,map的一个子类

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值