1.Spring中的IOC[控制反转]
没有Spring之前
public class Student{}
//new+构造函数
Student stu = new Student();
有Spring之后
public ?class ?Student{}
applicationContext.xml(Spring的核心配置文件)
<bean id="stu" class="com.bean.Student">
ApplicationContext ac=new ClassPathXmlApplicationContext("applicationContext.xml");
Student stu=ac.getBean("stu",Student.class);
在之前我们编写好的java类在创建对象的时候,都是new+构造方法来完成对象的创建,此时对象创建和维护的权利都控制在开发人员手中。
? ? ? ? IOC[控制反转]: 就是将对象的创建和维护权利从开发人员手中转移到Spring容器。 就是通过Spring容器来创建和维护对象。
IOC[控制反转]是一种思想概念,通过这个思想概念的具体实现操作Spring DI(依赖注入)
2.Spring中的DI[依赖注入]
依赖注入(Dependency Injection,DI)和控制反转含义相同,它们是从两个角度描述的同一个概念。
//被调用者
public class Student{
public String getStudent(){
return "网星";
}
}
//调用者
public class Person{
private Student stu=null;
public void testPerson(){
stu=new Student();
System.out.println(stu.getStudent());
}
}
调用者类【Person】在执行过程中需要使用被调用者【Student】类的对象,此时被调用者【Student】类的对象就是调用者类【Person】的依赖对象----依赖
注入---将依赖对象传递给调用者类【Person】的过程。
依赖注入----将依赖对象传递给调用者类中的过程。
在没有Spring的时候我们通过传递参数的方法将依赖对象传递给调用者类。
有了Spring以后对象创建和维护都是由Spring容器来完成,通过传递参数的方法将依赖对象传递给调用者。所以我们现在只能通过Spring容器来完成依赖注入。
通过Spring的配置文件【applicationContext.xml】完成依赖注入的方式。
1.setter注入:Set方法注入(嵌套property元素)
Student类【被调用者】
public class Student {
public String getTitle() {
return "一起来看流星雨";
}
}
Teacher类【调用者】
public class Teacher {
private Student param;
public void testPerson(){
String str = param.getTitle();
System.out.println(str);
}
public void setParam(Student param) {
this.param = param;
}
public Student getParam() {
return param;
}
}
applicationContext.xml【Spring核心配置文件】
<bean id="stu"class="com.bean.Student"></bean>
<bean id="person"class="com.bean.Person">
<!-- name:实例属性名
ref:引用/引入Spring创建的依赖对象
-->
<property name="param" ref="stu">
</bean>
2.构造函数注入(嵌套constructor-arg元素)
Student类(被调用者)
public class Student {
public String getTitle(){
return "你好啊,约的惹人";
}
}
Person类(调用者)
public class Person {
private Student parm2;
public Person(Student parm2) {
this.parm2 = parm2;
}
public Student getParm2() {
return parm2;
}
public void setParm2(Student parm2) {
this.parm2 = parm2;
}
public void fageTest(){
String title = parm2.getTitle();
System.out.println(title);
}
}
applicationContext.xml(Spring核心配置文件)
<bean id="stu" class="com.bean.Student"></bean>
<bean id="per" class="com.bean.Person">
<!--
name:调用者实例名
ref:引入/引用Spring的容器依赖对象
type:构造参数类型
index:构造函数的参数位置
-->
<constructor-arg name="parm2" ref="stu"></constructor-arg>:
</bean>
3.Spring实例化Bean的三种方法
通过Spring配置文件创建java类对象的方式
1)构造器实例化
构造器实例是指Spring容器通过Bean对应的类默认的构造函数实例化
Bean类
public class ConStroctorCreateObjectTest {
public void getBean(){
System.out.println("构造器实例化是指Spring容器通过Bean的id属性对应类默认构造实例Bean对象");
}
}
<bean id="csco" class="com.bean.ConStroctorCreateObjectTest">
2)实例工厂的方法实例化
需要提供一个静态工厂方法创建Bean的实例
被实例的类
public class Student{
public void testStudent(){
System.out.println("通过构造工厂创建的实例对象")
}
}
实例工厂类
public class StuFactory{
public Student getStudent(){
return new Student();
}
}
applicationContext.xml(核心配置文件)
<bean id="stu" class="com.bean.StuFactory"></bean>
<bean id="stuf" factory-bean="stu" factory-method="getStudent"></bean>
3)静态工厂的方式实例化
需要提供一个实例工厂方法创建 Bean 的实例。
实例类
public Student{
public void testStudent(){
System.out.println("静态工厂创建出来的对象")
}
}
静态工厂类
public StaticFactory{
public static Student getStudent(){
return new Student();
}
}
applicationContext.xml核心配置文件
<bean id="stu" class="com.bean.StaticFactroy" factory-method="getStudent"></bean>
测试代码
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
Student stu4 = ac.getBean("stu4", Student.class);
stu4.testStudent();
Student stu5 = ac.getBean("stu4",Student.class);
System.out.println("stu4===>" + stu4.hashCode());
System.out.println("stu5===>" + stu5.hashCode());
测试结果 👆
静态工厂创建出来的对象 stu4===>1558712965 stu5===>1558712965
4.Spring中Bean的作用域
Spring容器在初始化一个Bean的实例时,同时会指定该实例的有效范围
singleton | 单例模式,使用sinleton定义的Bean在Spring容器只有一个实例,这也是Bean默认的作用域。 | prototype?? | 原型模式,每次通过Spring容器获取prototype定义Bean时,Spring容器会创建一个新的Bean实例。 | request | 在一次HTTP请求中,容器会返回该Bean的同一个实例。而对不同的HTTP请求会返回不同的Bean实例,该作用域仅限于当前的HTTP request内有效 | session | 在一次 HTTP Session 中,容器会返回该 Bean 的同一个实例。而对不同的 HTTP 请求,会返回不同的实例,该作用域仅在当前 HTTP Session 内有效。 | global Session | 在一个全局的 HTTP Session 中,容器会返回该 Bean 的同一个实例。该作用域仅在使用 portlet context 时有效。 |
singleton : 单例模式
在 Spring 容器中只有一个实例,也是Bean 默认的作用域 <bean id="per" class="com.wangxing.demo4.PersonBean" scope="singleton"></bean>
ApplicationContext ac=new ClassPathXmlApplicationContext("applicationContext.xml");
PersonBean personBean1=ac.getBean("per", PersonBean.class);
PersonBean personBean2=ac.getBean("per", PersonBean.class);
System.out.println("personBean1==="+personBean1.hashCode());
System.out.println("personBean2==="+personBean2.hashCode());
if(personBean1.equals(personBean2)){
? ?System.out.println("同一个对象");
}
运行结果:
personBean1===>1558712965 personBean2===>1558712965
prototype : 原型模式
每次通过 Spring 容器获取Bean 时,容器都将创建一个新的 Bean 实例。 <bean id="per" class="com.wangxing.demo4.PersonBean" scope="prototype"></bean>
ApplicationContext ac=new ClassPathXmlApplicationContext("applicationContext.xml");
PersonBean personBean1=ac.getBean("per", PersonBean.class);
PersonBean personBean2=ac.getBean("per", PersonBean.class);
System.out.println("personBean1==="+personBean1.hashCode());
System.out.println("personBean2==="+personBean2.hashCode());
if(personBean1.equals(personBean2)){
? ?System.out.println("同一个对象");
}
运行结果
personBean1===>1558712965 personBean2===>208712506
5.Spring生命周期
Spring容器可以管理singleton作用域Bean的生命周期,再次作用域下,Spring也能够知道该Bean何时被创建,何时初始化完成,以及合适被销毁。
而对于prototype作用域的Bean,Spring只负责创建,当容器创建了一个Bean的实例后,Bean的实例就交给客户端代码管理,Spring容器将不再跟踪其生命周期。
了解Spring生命周期的意义在于,可以利用Bean在其存活的指定时刻做一些指定的操作。在一般情况下会在Bean被初始化或者销毁前执行一些操作。
在Spring中,Bean的生命周期是一个很复杂的执行过程,我们可以利用Spring提供一些定制的Bean创建过程。
Bean生命周期的整个执行过程描述。
1)根据配置情况调用Bean构造方法和工厂方法实例化Bean。
2)利用依赖注入完成Bean中所有属性值的配置注入。
3)如果Bean实现了BeanNameAware接口,则Spring调用了Bean的setBeanName()方法传入当前Bean的id。
4)如果Bean实现了BeanFactoryAware接口,则Spring调用setBeanFactroy()方法闯入当前工厂的实例引用。
5)如果Bean实现了ApplicationContextAware接口,则Spring调用setApplicationContext()方法,传入当前ApplicationContext实例引用。
6)如果BeanPostProcessor和Bean关联,则Spring将嗲偶哦那个该接口的于初始化方法
postProcessBeforeInitialzation() 对 Bean 进行加工操作,此处非常重要,Spring 的 AOP 就是利用它实现的。
7)如果Bean实现了InitializingBean接口,则Spring将调用afterPropertiesSet()方法。
8)如果在配置文件中通过init-method属性指定了初始化方法,则调用该初始化的方法
9)如果BeanPostProcessor关联Bean关联,则Spring将调用该接口初始化方法。postProcessAfterInitialization()。此时,Bean 已经可以被应用系统使用了。
10)如果在<bean>中指定了该Bean的作用范围为scope="singleton",则将该Bean放入SpringIoC的缓存池中,将触发Spring对该Bean的生命周期管理;如果<bean>中指定了该Bean作用范围scope="prototype",则将该Bean交给调用者,调用者管理Bean的声明周期,Spring不在管理该Bean.
11)如果Bean实现了DisposableBean接口,则Spring会调用destory()方法将Spring中的Bean销毁;如果在配置文件中通过destory-method属性定义了Bean的销毁方法,则Spring调用该方法对Bean进行销毁。
代码例子:
测试类
public class InitMethods {
public InitMethods(){
System.out.println("Spring创建对象");
}
public void initConfiginfo(){
System.out.println("Spring初始化方法");
}
private void destoryUse() {
System.out.println("销毁一些对象,比如连接池等等");
}
}
applicationContext.xml(Spring核心配置文件)
<bean id="initol" class="com.life.InitMethods" init-method="initConfiginfo" destroy-method="destoryUse"></bean>
测试主类
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
InitMethods initol = ac.getBean("initol", InitMethods.class);
AbstractApplicationContext ac1 = (AbstractApplicationContext) ac;
// ac1.close(); //关闭容器
ac1.registerShutdownHook(); //销毁容器
无奈源不够强大
?
|