先定义一个User类作为测试
public class User {
private String name;
private String pwd;
public User(){
System.out.println("无参构造方法执行");
}
public User(String name){
System.out.println("有参构造方法执行");
this.name=name;
}
public User(String name,String pwd){
System.out.println("有参构造方法执行");
this.name=name;
this.pwd=pwd;
}
public void show(){
System.out.println("用户:"+name);
if(pwd!=null){
System.out.println("密码:"+pwd);
}
}
public void setName(String name) {
System.out.println("set方法被执行");
this.name=name;
}
}
Spring配置文件为bean.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean name="hello" class="helloSpring.Hello">
<property name="name" value="张三"></property>
</bean>
<bean id="mysqlDao" class="helloSpring.UserDaoMySqlImpl"></bean>
<bean id="oracleDao" class="helloSpring.UserDaoOracleImpl"></bean>
<bean id="service" class="helloSpring.UserServiceImpl">
<property name="userDao" ref="mysqlDao"></property>
</bean>
<bean name="user" class="helloSpring.User">
<property name="name" value="李四"></property>
</bean>
<bean name="user1" class="helloSpring.User">
<constructor-arg index="0" value="王五"></constructor-arg> <!--index为构造方法参数的下标-->
</bean>
<bean name="user2" class="helloSpring.User">
<constructor-arg index="0" value="赵六"></constructor-arg>
<constructor-arg index="1" value="233333"></constructor-arg>
</bean>
<bean name="user3" class="helloSpring.User">
<constructor-arg type="java.lang.String" value="孙七"></constructor-arg>
<constructor-arg index="1" value="244444"></constructor-arg>
</bean>
<bean id="user4" class="helloSpring.UserStaticFactory" factory-method="newInstance"> <!--静态工厂-->
<constructor-arg index="0" value="钱八"></constructor-arg>
</bean>
<bean id="userDynamicFactory" class="helloSpring.UserDynamicFactory"></bean> <!--动态工厂-->
<bean id ="user5" factory-bean="userDynamicFactory" factory-method="newInstance">
<constructor-arg index="0" value="周九"></constructor-arg>
</bean>
</beans>
静态工厂
public class UserStaticFactory {
public static User newInstance(String s) {
return new User(s);
}
}
动态工厂
public class UserDynamicFactory {
public User newInstance(String name){
return new User(name);
}
}
测试类
package test;
import helloSpring.Hello;
import helloSpring.User;
import helloSpring.UserService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test {
public static void main(String[] args){
//解析beans.xml文件,生成管理相应的bean
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
// Hello hello = (Hello)context.getBean("hello");
// hello.show();
User user=(User)context.getBean("user");
user.show();
User user1=(User)context.getBean("user1");
user1.show();
User user2=(User)context.getBean("user2");
user2.show();
User user3=(User)context.getBean("user3");
user3.show();
User user4=(User)context.getBean("user4");
user4.show();
User user5=(User)context.getBean("user5");
user5.show();
}
}
hello被创建!
无参构造方法执行
set方法被执行
有参构造方法执行
有参构造方法执行
有参构造方法执行
有参构造方法执行
有参构造方法执行
用户:李四
用户:王五
用户:赵六
密码:233333
用户:孙七
密码:244444
用户:钱八
用户:周九
1.spring 在程序刚开始运行时就把对象创建好了,并且执行相应的构造函数,就算你从来没有应用该类,也同时给你把对象创建好了,如代码可见,Hello类被注释了仍然被创建并执行了构造方法。
2.spring进行创建对象方法1的过程中,必须要在对应类中定义set方法,可见
<bean name="user"class="helloSpring.User"><property name="name" value="李四"></property></bean>
本质是执行对应类中的set方法实现构造函数,而且执行无参构造。
3.spring进行创建对象方法 2,3,4可以指定构造参数的下标即index,执行有参构造。
4.静态工厂和动态工厂写法如上,但是他们不符合开闭原则:对扩展开放,对修改封闭。静态工厂增加需要是修改源代码,对修改不封闭。生产什么东西需要判断,因而仅适用于功能简单的代码(大致的理解)
在Spring中,bean可以被定义为两种模式:prototype(多例)和singleton(单例)
singleton(单例):只有一个共享的实例存在,所有对这个bean的请求都会返回这个唯一的实例。
prototype(多例):对这个bean的每次请求都会创建一个新的bean实例,类似于new。
Spring bean 默认是单例模式。
可以通过scope进行配置
<bean name="user" class="helloSpring.User" scope="singleton">
User user=(User)context.getBean("user");
User userx=(User)context.getBean("user");
System.out.println(user+" "+userx);
测试结果:
此取值时表明容器中创建时只存在一个实例,所有引用此bean都是单一实例。如同每个国家都有一个总统,国家的所有人共用此总统,而这个国家就是一个spring容器,总统就是spring创建的类的bean,国家中的人就是其它调用者,总统是一个表明其在spring中的scope为singleton,也就是单例模型。
此外,singleton类型的bean定义从容器启动到第一次被请求而实例化开始,只要容器不销毁或退出,该类型的bean的单一实例就会一直存活,典型单例模式,如同servlet在web容器中的生命周期。
spring容器在进行输出prototype的bean对象时,会每次都重新生成一个新的对象给请求方,虽然这种类型的对象的实例化以及属性设置等工作都是由容器负责的,但是只要准备完毕,并且对象实例返回给请求方之后,容器就不在拥有当前对象的引用,请求方需要自己负责当前对象后继生命周期的管理工作,包括该对象的销毁。也就是说,容器每次返回请求方该对象的一个新的实例之后,就由这个对象“自生自灭”,最典型的体现就是spring与struts2进行整合时,要把action的scope改为prototype。
如同分苹果,将苹果的bean的scope属性声明为prototype,在每个人领取苹果的时候,我们都是发一个新的苹果给他,发完之后,别人爱怎么吃就怎么吃,爱什么时候吃什么时候吃,但是注意吃完要把苹果核扔到垃圾箱!对于那些不能共享使用的对象类型,应该将其定义的scope设为prototype。
再次说明request,session和global session类型只实用于web程序,通常是和XmlWebApplicationContext共同使用。
<bean id ="requestPrecessor" class="...RequestPrecessor" scope="request" />
Spring容器,即XmlWebApplicationContext 会为每个HTTP请求创建一个全新的RequestPrecessor对象,当请求结束后,该对象的生命周期即告结束,如同java web中request的生命周期。当同时有100个HTTP请求进来的时候,容器会分别针对这10个请求创建10个全新的RequestPrecessor实例,且他们相互之间互不干扰,简单来讲,request可以看做prototype的一种特例,除了场景更加具体之外,语意上差不多。
对于web应用来说,放到session中最普遍的就是用户的登录信息,对于这种放到session中的信息,我们可以使用如下形式的制定scope为session:
<bean id ="userPreferences" class="...UserPreferences" scope="session" />
Spring容器会为每个独立的session创建属于自己的全新的UserPreferences实例,比request scope的bean会存活更长的时间,其他的方面没区别,如果java web中session的生命周期。
<bean id ="userPreferences" class="...UserPreferences" scope="globalsession" />
global session只有应用在基于porlet的web应用程序中才有意义,它映射到porlet的global范围的session,如果普通的servlet的web 应用中使用了这个scope,容器会把它作为普通的session的scope对待。
对IOC的总结,目前来说,感觉IOC可以很好的解耦合
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。