Spring
Spring是一个从实际开发中抽出来的框架,因此它完成了大量开发中的通用步骤,留给开发者的仅仅是与特定应用相关的部分,从而大大提高了企业应用的开发效率。
Spring为企业应用的开发提供了一个轻量级的解决方案。该解决方案包括:基于依赖注入的核心机制、基于AOP的声明事务管理、与多种持久层技术的整合,以及优秀的Web MVC框架等。
使用Spring管理Bean
Spring核心容器就是一个超级大工厂,所有的对象(包括数据源、Hibernate SessionFactory等基础性资源)都会被当成Spring核心容器管理的对象--Spring把容器中的一切对象统称为Bean。
Spring容器中的Bean,与Java Bean不同(Java Bean必须遵守一些特定的规范),Spring对Bean没有任何要求。只要是一个Java类,Spring就可以管理该Java类,并将它当成Bean处理。
配置Bean
<bean id=”对象名” class=”全限定类名”> <property name=”属性名” ref=”被依赖的Bean的对象名” /> </bean>
Spring配置Bean时,class属性的值必须是Bean实现类的完整类名,不能是接口,不能是抽象类,否则Spring无法使用反射创建该类的实例。
<property …/>子元素用于作为<bean …/>元素的子元素,它驱动Spring在底层以反射执行一次setter方法。name属性决定执行哪个setter方法,而value或ref决定执行setter方法的传入参数。如果传入的参数是基本类型或者其包装类、String等类型。则使用value属性指定传入参数。如果以容器中其他Bean作为传入参数,则使用ref属性指定传入参数。
<bean …/>元素的作用是:默认驱动Spring在底层调用无参构造函数创建对象。
Spring框架只要看到<property …/>子元素,Spring框架就会在底层以反射方式执行一次setter方法。何时执行这个setter方法呢?
该Bean一旦创建处理,Spring会立即根据<property …/>子元素来执行setter方法。
通过Spring容器中访问容器中的Bean,ApplicationContext是Spring容器中最常用的接口。该接口有两个实现类:
ClassPathXmlApplicationContext:从类加载路径下搜索配置文件,并根据配置文件来创建Spring容器。
FileSystemXmlApplicationContext:从文件系统的相对路径或绝地路径下去搜索配置文件,并根据配置文件来创建Spring容器。
//创建Spring容器 ApplicationContextctx = new ClassPathXmlApplicationContext(“配置文件名”);
Spring容器获取Bean对象主要有如下两个方法:
Object getBean(String id):根据容器中Bean的id来获取指定的Bean,获取Bean之后需要进行强制类型转换。
T getBean(String name,Class<T>):根据容器中的Bean的id来获取指定Bean,但该方法带一个泛型参数,因此获取Bean之后无须进行强制类型转换。
Spring框架最大的改变之一是程序不再使用new调用构造器创建Java对象,所有Java对象都由Spring容器负责创建。
Spring容器
Spring有两个核心接口:BeanFactory和ApplicationContext,其中ApplicationContext是BeanFactory的子接口。他们都可代表Spring容器,Spring容器是生成Bean实例的工厂,并管理容器中的Bean。
Spring容器创建对象的时机
默认为启动时创建Bean实例,为Bean配置一个bean,只创建一个对象,在底层使用了单例模式。
使用bean元素的属性 lazy-init = “true” 延迟加载(懒加载),lazy-init 和scope = “singleton” 结合使用。
Bean配置一个bean元素,每次创建一个新的对象,而不是使用时一个对象时,需要为bean元素配置 scope = "prototype"
prototype:每次通过容器的getBean()方法获取prototype作用域的Bean时,都将产生一个新的Bean实例。
Spring核心机制:依赖注入
依赖注入:简单的来说,A对象要调用B对象中的方法,也就可以说A依赖于B。
Spring框架的核心功能有两个:
①Spring容器作为超级大工厂,负责创建、管理所有的Java对象(Bean)
②Spring容器管理容器中Bean之间的依赖关系,Spring使用一种“依赖注入”的方式来管理Bean之间的依赖关系。
依赖注入是一种优秀的解耦方式。依赖注入让Spring的Bean以配置文件组织在一起,而不是以硬编码的方式耦合在一起。使用Spring框架,调用者获取被依赖对象的方式由原来的主动获取,变成了被动接受,被称为控制反转。
从Spring容器的角度来看,Spring容器负责将被依赖对象赋值给调用者的成员变量,相当于为调用者注入它依赖的实例,被称为依赖注入。
控制反转和依赖注入其实是同一个行为的两种表达方式,只是描述的角度不同而已。
举一个通俗易懂的例子
一个人(Java实例,调用者)需要斧头(Java实例,被依赖对象)来干活。
在原始社会,需要斧头的人(调用者)只能自己去磨一把斧头(被依赖对象)。对应的情形为:Java程序里的调用者自己创建被依赖对象,通常采用new关键字调用构造器创建一个被依赖对象。
进入工业社会,工厂出现了,斧头不再由普通人完成,而在工厂里被生成出来,此时需要斧头的人(调用者)找到工厂,购买斧头,无须关心斧头的制造过程。对应简单的工厂设计模式,调用者只需定位工厂,无须理会被依赖对象的具体实现过程。
进入共产主义社会,需要斧头的人甚至无须定义工厂,“坐等”社会提供即可。调用者无须关心被依赖对象的实现,无须理会工厂,等待Spring依赖注入。
依赖注入通常有两种
设值注入:IoC容器使用成员变量的setter方法来注入被依赖对象。
构造注入:IoC容器使用构造器来注入被依赖对象。
设值注入
这种注入方式简单,直观,在Spring的依赖注入中大量使用。
下面的例子集成了设值注入的各种情形,如为基本类型,数组,引用数组,List,Set,Map,和Properties属性注值。
public class Student { //标志属性 private int id; //学生编号 private String stuNo; //学生姓名 private String stuName; //学生爱好 private String[] hobbys; //喜欢的演员 private Actor[] actors; //上过的学校 private List<String> schools; //爱听的歌 private Set<String> songs; //代课的老师 private List<Teacher> techers; //选的课程 private Set<Course> course; //联系方式 private Map<String,String> links; //课程成绩 private Map<Course,String> scores; //健康状况 private Properties health; //省略了setter和getter方法 }
public class Actor { private int id; private String actName; //省略了setter和getter方法 } public class Teacher { private int id; private String teaNo; private String teaName; //省略了setter和getter方法 } public class Course { private int id; private String courNo; private String courName; //省略了setter和getter方法 }
在application.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"> <!-- 创建teacher对象,并注入值--> <bean id="teacher1" class="com.ghq.model.entity.Teacher"> <property name="id" value="1"/> <property name="teaNo" value="t001"/> <property name="teaName" value="杨教授"/> </bean> <bean id="teacher2" class="com.ghq.model.entity.Teacher"> <property name="id" value="2"/> <property name="teaNo" value="t002"/> <property name="teaName" value="李教授"/> </bean> <!-- 创建course对象,并注入值--> <bean id="course1" class="com.ghq.model.entity.Course"> <property name="id" value="1"/> <property name="courNo" value="c001"/> <property name="courName" value="数据结构"/> </bean> <bean id="course2" class="com.ghq.model.entity.Course"> <property name="id" value="2"/> <property name="courNo" value="c002"/> <property name="courName" value="计算机网络"/> </bean> <!-- 创建actor对象,并注入值--> <bean id="actor1" class="com.ghq.model.entity.Actor" > <property name="id" value="1"/> <property name="actName" value="薛之谦"/> </bean> <bean id="actor2" class="com.ghq.model.entity.Actor" > <property name="id" value="2"/> <property name="actName" value="周杰伦"/> </bean> <!-- 创建student对象,并注入值--> <bean id="student" class="com.ghq.model.entity.Student"> <!-- 基本类型,String等赋值--> <property name="id" value="1"/> <property name="stuNo" value="s001"/> <property name="stuName" value="张三"/> <!-- 基本类型数组赋值--> <property name="hobbys"> <array> <value>睡觉</value> <value>打游戏</value> </array> </property> <!-- 引用类型数组赋值--> <property name="actors"> <array> <ref bean="actor1"/> <ref bean="actor2"/> </array> </property> <!-- list集合(基本类型)赋值--> <property name="schools"> <list> <value>清华大学</value> <value>北京大学</value> </list> </property> <!-- set集合(基本类型)赋值--> <property name="songs"> <set> <value>小苹果</value> <value>我们不一样</value> </set> </property> <!-- list集合(引用类型)赋值--> <property name="techers"> <list> <ref bean="teacher1"/> <ref bean="teacher2"/> </list> </property> <!-- set集合(引用类型)赋值--> <property name="course"> <set> <ref bean="course1"/> <ref bean="course2"/> </set> </property> <!-- map集合(基本类型)赋值--> <property name="links"> <map> <entry key="phone" value="1234567890"></entry> <entry key="QQ" value="987654"></entry> </map> </property> <!-- map集合(引用类型)赋值--> <property name="scores"> <map> <entry key-ref="course1" value="88"></entry> <entry key-ref="course2" value="77"></entry> </map> </property> <!-- Properties类型赋值--> <property name="health"> <props> <prop key="height">170</prop> <prop key="weight">130</prop> </props> </property> </bean> </beans>
测试输出结果为
public class Test { public static void main(String[] args) { ApplicationContext fac = new ClassPathXmlApplicationContext("application.xml"); Student stu = fac.getBean("student", Student.class); System.out.println(stu.toString()); }}
Student,Actor,Course,Teacher中均有toString方法,将属性一次性输出
运行结果为:
Student [id=1, stuNo=s001, stuName=张三, hobbys=[睡觉, 打游戏], actors=[Actor [id=1, actName=薛之谦], Actor [id=2, actName=周杰伦]], schools=[清华大学, 北京大学], songs=[小苹果, 我们不一样], techers=[Teacher [id=1, teaNo=t001, teaName=杨教授], Teacher [id=2, teaNo=t002, teaName=李教授]], course=[Course [id=1, courNo=c001, courName=数据结构], Course [id=2, courNo=c002, courName=计算机网络]], links={phone=1234567890, QQ=987654}, scores={Course [id=1, courNo=c001, courName=数据结构]=88, Course [id=2, courNo=c002, courName=计算机网络]=77}, health={height=170, weight=130}]
构造注入
这种方式在构造实例时,已经为其完成了依赖关系的初始化。这种利用构造器来设置依赖关系的方式,称为构造注入。
通俗来讲就是通过Spring在底层以反射方式执行带指定参数的构造器,当执行带参数的构造器时,就可利用构造参数对成员变量执行初始化。
使用构造注入,在类中不用提供setter方法,提供带参数的构造器。
<bean id=”对象名” class=”全限定类名”> <constructor-arg ref=”参数” /> </bean>
原文地址:https://www.cnblogs.com/ghq120/p/8327701.html