1.Spring是什么
Spring是一个开源框架,Spring是于2003 年兴起的一个轻量级的Java 开发框架,由Rod Johnson 在其著作Expert One-On-One J2EE Development and Design中阐述的部分理念和原型衍生而来。它是为了解决企业应用开发的复杂性而创建的。框架的主要优势之一就是其分层架构,分层架构允许使用者选择使用哪一个组件,同时为 J2EE 应用程序开发提供集成的框架。Spring使用基本的JavaBean来完成以前只可能由EJB完成的事情。然而,Spring的用途不仅限于服务器端的开发。从简单性、可测试性和松耦合的角度而言,任何Java应用都可以从Spring中受益。Spring的核心是控制反转(IoC)和面向切面(AOP)。
2.Spring的优点
①、方便解耦,简化开发
通过Spring提供的IoC容器,我们可以将对象之间的依赖关系交由Spring进行控制,避免硬编码所造成的过度程序耦合。有了Spring,用户不必再为单实例模式类、属性文件解析等这些很底层的需求编写代码,可以更专注于上层的应用。
②、AOP编程的支持
通过Spring提供的AOP功能,方便进行面向切面的编程,许多不容易用传统OOP实现的功能可以通过AOP轻松应付。
③、声明式事务的支持
在Spring中,我们可以从单调烦闷的事务管理代码中解脱出来,通过声明式方式灵活地进行事务的管理,提高开发效率和质量。
④、方便程序的测试
可以用非容器依赖的编程方式进行几乎所有的测试工作,在Spring里,测试不再是昂贵的操作,而是随手可做的事情。例如:Spring对Junit4支持,可以通过注解方便的测试Spring程序。
⑤、方便集成各种优秀框架
Spring不排斥各种优秀的开源框架,相反,Spring可以降低各种框架的使用难度,Spring提供了对各种优秀框架(如Struts,Hibernate、Hessian、Quartz)等的直接支持。
⑥、降低Java EE API的使用难度
Spring对很多难用的Java EE API(如JDBC,JavaMail,远程调用等)提供了一个薄薄的封装层,通过Spring的简易封装,这些Java EE API的使用难度大为降低。
⑦、Java 源码是经典学习范例
Spring的源码设计精妙、结构清晰、匠心独运,处处体现着大师对Java设计模式灵活运用以及对Java技术的高深造诣。Spring框架源码无疑是Java技术的最佳实践范例。如果想在短时间内迅速提高自己的Java技术水平和应用开发水平,学习和研究Spring源码将会使你收到意想不到的效果。
3.Spring需要的jar包
4.spring配置文件
pojo实体类
package com.pojo;
public class Student {
private int sid;
private String name;
public Student() {
super();
}
public Student(int sid, String name) {
super();
this.sid = sid;
this.name = name;
}
public int getSid() {
return sid;
}
public void setSid(int sid) {
this.sid = sid;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Student{" +
"sid=" + sid +
", name='" + name + '\'' +
'}';
}
}
IOC(控制反转)
构造函数创建Bean
配置文件
<?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-2.5.xsd">
<!--通过构造器创建Bean
id 唯一标识,可以任意命名一般为类的首字母小写
class 类的全地址-->
<bean id="student1" class="com.pojo.Student">
<!--初始化时注入属性,需要类生成set方法-->
<property name="name" value="张三"/>
<property name="sid" value="1"/>
</bean>
<!--用带参的构造器给属性初始化-->
<bean id="student2" class="com.pojo.Student" scope="singleton">
<constructor-arg index="0" value="1"></constructor-arg>
<constructor-arg index="1" value="jack"></constructor-arg>
</bean>
</beans>
测试类
public class Test1 {
public static void main(String[] args) {
/*创建spring容器对象*/
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
/*通过spring容器获取student对象*/
Student student1 = (Student) ac.getBean("student1");
System.out.println(student1);
Student student2 = (Student) ac.getBean("student2");
System.out.println(student2);
}
}
运行结果
七月 25, 2019 9:30:10 上午 org.springframework.context.support.ClassPathXmlApplicationContext prepareRefresh
信息: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@31221be2: startup date [Thu Jul 25 09:30:10 CST 2019]; root of context hierarchy
七月 25, 2019 9:30:10 上午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
信息: Loading XML bean definitions from class path resource [applicationContext.xml]
Student{sid=1, name='张三'}
Student{sid=1, name='jack'}
静态工厂方法创建Bean
静态工厂类
public class StaticStudentFactory {
private static Student student;
public static Student getStudent(int sid,String name) {
student = new Student(sid,name);
return student;
}
}
配置文件
<?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-2.5.xsd">
<!--通过静态工厂创建Bean
id 唯一标识,可以任意命名一般为类的首字母小写
class 类的全地址
factory-method 获取实例化对象的方法-->
<bean id="student3" class="com.factory.StaticStudentFactory" factory-method="getStudent">
<!--方法需要的参数
index 第几个参数,从0开始
value 注入参数的值-->
<constructor-arg index="0" value="1"/>
<constructor-arg index="1" value="Tom"/>
</bean>
</beans>
测试类
public class Test1 {
public static void main(String[] args) {
/*创建spring容器对象*/
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
/*通过spring容器获取student对象*/
Student student3 = (Student) ac.getBean("student3");
System.out.println(student3);
}
}
运行结果
七月 25, 2019 9:34:47 上午 org.springframework.context.support.ClassPathXmlApplicationContext prepareRefresh
信息: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@31221be2: startup date [Thu Jul 25 09:34:47 CST 2019]; root of context hierarchy
七月 25, 2019 9:34:48 上午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
信息: Loading XML bean definitions from class path resource [applicationContext.xml]
Student{sid=1, name='Tom'}
Process finished with exit code 0
实例化工厂
实例化工厂类
public class InstanceStudentFactory {
private Student student;
public Student getStudent(int sid,String name){
student = new Student(sid,name);
return student;
}
}
配置文件
<?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-2.5.xsd">
<!--通过实例化工厂创建Bean-->
<!--将实例化工厂InstanceStudentFactory交给spring管理-->
<bean id="StudentFactory" class="com.factory.InstanceStudentFactory">
</bean>
<!--factory-bean 工厂Bean 引用上面交给spring管理的工厂
factory-method 工厂中生产student的方法-->
<bean id="student4" factory-bean="StudentFactory" factory-method="getStudent">
<!--方法需要的参数
index 第几个参数,从0开始
value 注入参数的值-->
<constructor-arg index="0" value="1"/>
<constructor-arg index="1" value="roes"/>
</bean>
</beans>
测试类
public class Test1 {
public static void main(String[] args) {
/*创建spring容器对象*/
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
/*通过spring容器获取student对象*/
Student student4 = (Student) ac.getBean("student4");
System.out.println(student4);
}
}
运行结果
七月 25, 2019 9:44:53 上午 org.springframework.context.support.ClassPathXmlApplicationContext prepareRefresh
信息: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@31221be2: startup date [Thu Jul 25 09:44:53 CST 2019]; root of context hierarchy
七月 25, 2019 9:44:53 上午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
信息: Loading XML bean definitions from class path resource [applicationContext.xml]
Student{sid=1, name='roes'}
Process finished with exit code 0
使用注解
配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd">
<!--开启spring扫描,可能在那些包下有注解,多个使用,隔开。也可以直接写com-->
<context:component-scan base-package="com.pojo"></context:component-scan>
</beans>
需要导入context的xsd
package com.pojo;
import org.springframework.stereotype.Component;
/*value 获取Bean的id
* 可以省略直接写@Component 则id为类名首字母小写*/
@Component(value = "abc")
public class Student {
private int sid;
private String name;
public Student() {
super();
}
public Student(int sid, String name) {
super();
this.sid = sid;
this.name = name;
}
public int getSid() {
return sid;
}
public void setSid(int sid) {
this.sid = sid;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Student{" +
"sid=" + sid +
", name='" + name + '\'' +
'}';
}
}
只需要在类的上面加上@Component注解。value 获取Bean的id 可以省略直接写@Component 则id为类名首字母小写
DI(依赖注入)
pojo实体类
Dog类只有一个String name的属性
package com.pojo;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
public class People {
private int id;
private String name;
private List<String> list;
private Set<String> set;
private Map<String,String> map;
private Properties prop;
private Dog dog;
public People(int id, String name, List<String> list, Set<String> set, Map<String, String> map, Properties prop, Dog dog) {
this.id = id;
this.name = name;
this.list = list;
this.set = set;
this.map = map;
this.prop = prop;
this.dog = dog;
}
public People() {
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<String> getList() {
return list;
}
public void setList(List<String> list) {
this.list = list;
}
public Set<String> getSet() {
return set;
}
public void setSet(Set<String> set) {
this.set = set;
}
public Map<String, String> getMap() {
return map;
}
public void setMap(Map<String, String> map) {
this.map = map;
}
public Properties getProp() {
return prop;
}
public void setProp(Properties prop) {
this.prop = prop;
}
public Dog getDog() {
return dog;
}
public void setDog(Dog dog) {
this.dog = dog;
}
@Override
public String toString() {
return "People{" +
"id=" + id +
", name='" + name + '\'' +
", list=" + list +
", set=" + set +
", map=" + map +
", prop=" + prop +
", dog=" + dog +
'}';
}
}
通过Set方法注入属性
配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.0.xsd">
<!--加载外部文件,交给spring管理,用于给properties属性注入-->
<bean id="lq" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<property name="locations">
<list>
<value>classpath*:lq.properties</value>
</list>
</property>
</bean>
<!--将Dog类交给spring管理-->
<bean id="dog" class="com.pojo.Dog">
<property name="name" value="来福"/>
</bean>
<!--通过属性的set方法注入-->
<bean id="people" class="com.pojo.People">
<!--String类型和基本类型注入
name 属性名
value 给属性赋值-->
<property name="id" value="1"></property>
<property name="name" value="李青 "></property>
<!--list类型注入
name 属性名
value 一个元素-->
<property name="list">
<list>
<value>打野</value>
<value>上单</value>
<value>辅助</value>
<value>中单</value>
</list>
</property>
<!--set类型注入
name 属性名
value 一个元素-->
<property name="set">
<set>
<value>aaa</value>
<value>bbb</value>
<value>ccc</value>
<value>aaa</value>
</set>
</property>
<!--map类型注入
name 属性名
entry 一个元素-->
<property name="map">
<map >
<entry key="装备1" value="无尽之刃"></entry>
<entry key="装备2" value="饮血剑"></entry>
<entry key="装备3" value="绿叉"></entry>
<entry key="装备4" value="羊刀"></entry>
</map>
</property>
<!--用ref引用propertiesBean的id-->
<property name="prop" ref="lq"></property>
<!--自定义类直接饮用其Bean的id-->
<property name="dog" ref="dog"></property>
</bean>
</beans>
外部文件lq.propert
k1=aaa
k2=bbb
k3=ccc
k4=ddd
测试类
package com.test;
import com.pojo.People;
import com.pojo.Student;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test1 {
public static void main(String[] args) {
/*创建spring容器对象*/
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
/*通过spring容器获取student对象*/
People people = (People) ac.getBean("people");
System.out.println(people);
}
}
运行结果
七月 25, 2019 11:12:03 上午 org.springframework.context.support.ClassPathXmlApplicationContext prepareRefresh
信息: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@31221be2: startup date [Thu Jul 25 11:12:03 CST 2019]; root of context hierarchy
七月 25, 2019 11:12:03 上午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
信息: Loading XML bean definitions from class path resource [applicationContext.xml]
七月 25, 2019 11:12:03 上午 org.springframework.beans.factory.config.PropertiesFactoryBean loadProperties
信息: Loading properties file from URL [file:/C:/Users/lx/Desktop/01spring/out/production/01spring/lq.properties]
People{id=1, name='李青 ', list=[打野, 上单, 辅助, 中单], set=[aaa, bbb, ccc], map={装备1=无尽之刃, 装备2=饮血剑, 装备3=绿叉, 装备4=羊刀}, prop={k4=ddd, k3=ccc, k2=bbb, k1=aaa}, dog=Dog{name='来福'}}
Process finished with exit code 0
构造器注入属性
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.0.xsd">
<!--加载外部文件,交给spring管理,用于给properties属性注入-->
<bean id="lq" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<property name="locations">
<list>
<value>classpath*:lq.properties</value>
</list>
</property>
</bean>
<!--将Dog类交给spring管理-->
<bean id="dog" class="com.pojo.Dog">
<property name="name" value="来福"/>
</bean>
<!--通过构造器注入-->
<bean id="people" class="com.pojo.People">
<!--按照构造器中属性的排列顺序,从0开始,一一对应。几个属性可以调换顺序但是index value一定要对应
index 第几个参数
valus 参数赋值-->
<constructor-arg index="0" value="1"/>
<constructor-arg index="1" value="李青"/>
<!--
type 参数的类型,需要全称-->
<constructor-arg index="2" type="java.util.List">
<list>
<value>打野</value>
<value>上单</value>
<value>辅助</value>
<value>中单</value>
</list>
</constructor-arg>
<constructor-arg index="3" type="java.util.Set">
<set>
<value>aaa</value>
<value>bbb</value>
<value>ccc</value>
<value>aaa</value>
</set>
</constructor-arg>
<constructor-arg index="4" type="java.util.Map">
<map >
<entry key="装备1" value="无尽之刃"></entry>
<entry key="装备2" value="饮血剑"></entry>
<entry key="装备3" value="绿叉"></entry>
<entry key="装备4" value="羊刀"></entry>
</map>
</constructor-arg>
<!--properties文件,自定义类交给spring管理后可以直接引用,ref=引用id-->
<constructor-arg index="5" type="java.util.Properties" ref="lq">
</constructor-arg>
<constructor-arg type="com.pojo.Dog" ref="dog"></constructor-arg>
</bean>
</beans>
运行结果
七月 25, 2019 11:19:56 上午 org.springframework.context.support.ClassPathXmlApplicationContext prepareRefresh
信息: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@31221be2: startup date [Thu Jul 25 11:19:56 CST 2019]; root of context hierarchy
七月 25, 2019 11:19:56 上午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
信息: Loading XML bean definitions from class path resource [applicationContext.xml]
七月 25, 2019 11:19:57 上午 org.springframework.beans.factory.config.PropertiesFactoryBean loadProperties
信息: Loading properties file from URL [file:/C:/Users/lx/Desktop/01spring/out/production/01spring/lq.properties]
People{id=1, name='李青', list=[打野, 上单, 辅助, 中单], set=[aaa, bbb, ccc], map={装备1=无尽之刃, 装备2=饮血剑, 装备3=绿叉, 装备4=羊刀}, prop={k4=ddd, k3=ccc, k2=bbb, k1=aaa}, dog=Dog{name='来福'}}
Process finished with exit code 0
通过注解实现注入
配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd"
default-autowire="byName">
<!--在beans的default-autowire属性中设置全局自动装配方式为byName,也可以针对某个Bean单独设置-->
<!--开启com.pojo包的扫描-->
<context:component-scan base-package="com.pojo"/>
</beans>
pojo实体类
package com.pojo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
@Component
public class Demo {
/*@Autowired是根据类型自动装配的,加上@Qualifier则可根据byName的方式自动装配,其中@Qualifier不能单独使用。
*@Qualifier(value = "student") 括号中的value属性必须有不然会报错
*@Resource如有指定的name属性,先按该属性进行byName方式查找装配;其次再进行默认的byName方式进行装配; 以上都不成功,则按byType的方式自动装配。@Resource(name="student")括号中可不写。
*@Autowired,@Qualifier是spring提供的注解 @Resource是Java提供的注解 */
@Autowired
@Qualifier(value = "student")
@Resource(name="student")
private Student student;
public Student getStudent() {
return student;
}
public void setStudent(Student student) {
this.student = student;
}
@Override
public String toString() {
return "Demo{" +
"student=" + student +
'}';
}
}
运行结果
七月 25, 2019 11:47:56 上午 org.springframework.context.support.ClassPathXmlApplicationContext prepareRefresh
信息: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@31221be2: startup date [Thu Jul 25 11:47:56 CST 2019]; root of context hierarchy
七月 25, 2019 11:47:56 上午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
信息: Loading XML bean definitions from class path resource [applicationContext.xml]
Demo{student=Student{sid=0, name='null'}}
Process finished with exit code 0
student被初始化,没有初始化属性。