1.Singleton和Protype的区别。
两者都是bean标签里的东西,用scope来标注。
1.1当scope为Singleton时,创建的对象是全局唯一的(开辟一块唯一的空间,不管使用这个bean标签创建多少个对象,最终只会调用相同空间中的唯一的那个对象)。简单举例,假设通过该bean标签创建两个对象分别为A和B,那么A,B对象的空间地址是一样的,也就是说这两个对象是共享同一个空间的。
除此之外,singleton创建对象是在
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
这段代码运行时就被创建的,也就是将其丢入容器后就立刻创建了对象,不管是否调用
提问,是否说明这两个对象是同一个内容?
我认为是一样的,毕竟都是同一个地址。
1.2当scope为Protype时,创建的对象是多例的(也就是每创建一个对象,就会new一块存储空间)。
当对应的bean标签被调用的时候,才会创建对象。
1.3简单分别singleton和protype的原则就是看内存空间的开辟情况,以及创建对象的时机,个人认为()。
2.静态工厂创建:
首先构建一个静态工厂类:
package com.hxy; import com.hxy.impl.UserDaoimpl; public class StaticFactory { private static UserDao userDao (){ return new UserDaoimpl(); } } 相当于构建了一个多态,
对应的UserDao和其实现类UserDaoimpl:
package com.hxy.impl; import com.hxy.UserDao; public class UserDaoimpl implements UserDao { @Override public void method() { System.out.println("UserDaoimpl method"); } public UserDaoimpl() {System.out.println("无参构造函数");} }
package com.hxy; public interface UserDao { public void method(); }
目前的spring配置文件
<?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 id="UserDaoimpl" class="com.hxy.impl.UserDaoimpl" scope="singleton"></bean>
<bean id="UserDaoimpl2" class="com.hxy.StaticFactory" factory-method="userDao" scope="singleton"></bean>
</beans>
测试类来简单实验
import com.hxy.UserDao;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class UserDaoTest {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
UserDao userDaoimpl2 = (UserDao)context.getBean("UserDaoimpl2");
System.out.println(userDaoimpl2);
}
}
最终的输出结果:
无参构造函数
无参构造函数
com.hxy.impl.UserDaoimpl@6adede5
最开始很疑惑为什么会输出两次无参构造,但回顾singleton的使用方法后,发现即使我的测试类没有创建UserDaoimpl,但是我的spring.xml配置文件中有 <bean id="UserDaoimpl" class="com.hxy.impl.UserDaoimpl" scope="singleton"></bean>,并且测试类中有ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");那么就会在创建容器的那一瞬间创建好UserDaoimpl,在我的UserDaoimpl中也有构造函数完成后就输出“无参构造函数”的逻辑,所以最后会输出两次“无参构造函数”以及UserDaoimpl2的地址。
3.工厂实例创建:
创建了一个新的工厂类,
package com.hxy.impl; import com.hxy.UserDao; public class Factory { public UserDao userDao() { return new UserDaoimpl(); } }
修改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 id="UserDaoimpl" class="com.hxy.impl.UserDaoimpl" scope="singleton"></bean>--> <!-- <bean id="UserDaoimpl2" class="com.hxy.StaticFactory" factory-method="userDao" scope="singleton"></bean>--> <bean id="Factory" scope="prototype" class="com.hxy.impl.Factory"></bean> <bean id="UserDaoimpl3" factory-bean="Factory" factory-method="userDao" ></bean> </beans>
import com.hxy.UserDao;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class UserDaoTest {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
// UserDao userDaoimpl2 = (UserDao)context.getBean("UserDaoimpl2");
// System.out.println(userDaoimpl2);
UserDao userDaoimpl3 = (UserDao)context.getBean("UserDaoimpl3");
System.out.println(userDaoimpl3);
UserDao userDaoimpl4 = (UserDao)context.getBean("UserDaoimpl3");
System.out.println(userDaoimpl4);
}
}
测试类对新建的工厂对象进行输出,输出的地址却是一样的,这很奇怪,最后发现错误出在配置的过程中
<bean id="Factory" scope="prototype" class="com.hxy.impl.Factory"></bean>
<bean id="UserDaoimpl3" factory-bean="Factory" factory-method="userDao" ></bean>
首先说这个内容的意义,两排内容构建一个工厂类,与静态工厂不同。
工厂类需要首先构建一个工厂类,然后调用工厂类的方法构建出需要类的实例userDao,并且在上述配置文件的第二排中没有设置scope=protype,所以默认scope为singleton,这就导致通过工厂类创建两个userDao实例的地址是相同的。