Spring v4

    xiaoxiao2022-07-07  163

    Spring v4.2框架–入门

    1.Spring概述

    a)什么是Spring

    Spring是一个分层的JavaSE/EEfull-stack(一站式)轻量级开源框架。

    一站式框架:有SE/EE开发的每一层解决方案

    WEB层:SpringMVCService层:Spring的Bean管理,Spring声明式事务DAO层:Spring的JdbcTemplate,Spring的ORM模块

    b)Spring的优点

    1.轻量

    2.控制反转(IoC):解决程序之间的耦合

    3.面向切面

    2.SpringIOC入门(XML)

    **IOC(Inversion of Control)**控制反转:将对象的创建权交给Spring。

    a)下载Spring的开发包

    官网地址:https://spring.io/

    Docs:Spring的开发规范和api

    libs:Spring开发的jar包和源码

    schema:Spring配置文件的约束

    b)搭建环境

    创建Web项目,引入jar包。

    创建对应的接口和类

    传统方式的缺陷:如何底层的实现切换了,需要修改源代码。
    能不能不修改程序源代码对程序进行扩展?
    Spring的IoC的底层实现
    传统方式:

    创建对象

    UserDao dao = new UserDao(); //面向接口编程:方便程序的扩展 //缺陷:接口和实现类有耦合(联系过于紧密,切换底层实现类,必须修改底层源代码) UserDao dao = new UserDaoImpl();

    好的程序设计必须满足OCP原则,在尽量不修改程序源码的基础上对程序进行扩展

    解决方式1:工厂模式,把所有类的创建交给工厂

    UserDao dao = DaoFactory.getUserDao(); //接口和实现类之间没有耦合,但是接口和工厂有耦合。

    解决方式2:工厂+反射+配置文件,实现程序的解耦合(Spring IoC的底层实现原理)

    <bean id="userDao" class="xxx.UserDaoImpl"></bean> class BeanFactory{ public static Object getBean(String id){ //解析XML,通过id查找class //反射 Class class = Class.forName(); return class.newInstance(); } }

    3.Spring的Bean管理

    将实现类交给Spring管理

    在src目录下新建applicationContext.xml(可以是其他名字,默认):

    约束文件在spring-framework-4.2.4.RELEASE-dist\spring-framework-4.2.4.RELEASE\docs\spring-framework-reference\html\xsd-configuration.html中寻找the beans schema

    <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">

    applicationContext.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"> <!-- Spring入门配置 --> <bean id="userDao" class="com.nike.spring.demo01.UserDaoImpl"></bean> </beans>

    log4j配置文件:log4j.properties

    ### direct log messages to stdout ### log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.Target=System.err log4j.appender.stdout.layout=org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n ### direct messages to file mylog.log ### log4j.appender.file=org.apache.log4j.FileAppender log4j.appender.file.File=c\:mylog.log log4j.appender.file.layout=org.apache.log4j.PatternLayout log4j.appender.file.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n ### set log levels - for more verbose logging change 'info' to 'debug' ### # error warn info debug trace log4j.rootLogger= info, stdout
    编写测试类
    package com.nike.spring.demo01; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; /** * Spring的入门 * @author 猪猪 */ public class SpringDemo1 { /** * 传统方式的调用 */ @Test public void demo1(){ UserDao dao = new UserDaoImpl(); dao.save(); } @Test /** * Spring方式的调用 * */ public void demo2(){ //创建Spring工厂 ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml"); UserDao dao = (UserDao) applicationContext.getBean("userDao"); dao.save(); } }

    c)IoC与DI的区别

    IoC:控制反转,将对象的创建权反转给了Spring

    DI:依赖注入,前提必须要有IoC的环境,Spring在管理这个类的时候将类的依赖属性注入(设置)进来

    对象与对象之间的关系

    依赖:A类在B类的某一个方法中做参数,要将A类的实例传入B类的方法

    继承:extends,is a,

    聚合:has a,A类是B类的一个属性,松散,紧密

    package com.nike.spring.demo01; /** * 用户管理业务逻辑层的一个实现类 * @author 猪猪 */ public class UserDaoImpl implements UserDao { private String name; public void setName(String name){ this.name = name; } public void save() { System.out.println("UserService执行了..."+name); } } <?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"> <!-- Spring入门配置 --> <bean id="userDao" class="com.nike.spring.demo01.UserDaoImpl"> <property name="name" value="lisi"/> </bean> </beans> package com.nike.spring.demo01; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; /** * Spring的入门 * @author 猪猪 */ public class SpringDemo1 { /** * 传统方式的调用 */ @Test public void demo1(){ UserDaoImpl dao = new UserDaoImpl(); dao.setName("zhangsan"); dao.save(); } @Test /** * Spring方式的调用 * */ public void demo2(){ //创建Spring工厂 ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml"); UserDao dao = (UserDao) applicationContext.getBean("userDao"); dao.save(); } }

    5.Spring工厂类的概述

    Spring提供了两个工厂类:ApplicationContext,BeanFactory

    BeanFactory(老版本工厂类)

    ApplicationContext(新版本工厂类)

    区别:

    BeanFactory是Spring工厂类的最上层结构,ApplicationContext继承了BeanFactory接口

    ApplicationContext有两个具体实现类,FileSystemXmlApplicationContext和ClassPathXmlApplicationContext

    BeanFactory:调用getBean()方法的时候才会生成类实例。

    ApplicationContext:加载配置文件时就会将Spring管理的类都实例化。

    FileSystemXmlApplicationContext:

    加载文件系统下的配置文件(本地磁盘)。

    ClassPathXmlApplicationContext:

    加载类路径下的配置文件。src目录下的配置文件,最终会翻译到class目录下

    6.XML的提示的配置

    a)Schema的配置

    一个xml只能被一个DTD约束,可以被多个Schema约束。

    b)Bean的生命周期的配置

    (1)<bean>标签的id和name配置

    id:使用了约束中的唯一约束,里面不能出现任何特殊字符,

    name:没有使用约束中的唯一约束(理论上可以出现重复,实际开发中不能重复),name中可以出现特殊字符。

    在Spring和Struts1整合时可能会出现特殊字符。<bean name="/user" class=“xxx”>

    class:要生成实例的类的全路径。

    (2)bean生命周期的配置

    init-method:Bean初始化时执行的方法

    destory-method:Bean被销毁的时候执行的方法(Bean时单例创建的,默认就是单例创建,工厂关闭,Bean销毁)

    c)Bean的作用范围的配置(重点),通过scope属性进行配置

    scope:代表Bean的作用范围,取值有:

    singleton:默认的,采用单例模式创建这个对象(主要)

    prototype:多例模式,(主要,Struts2和Spring整合时一定会用到)

    request:应用在Web项目中,Spring创建这个类实例后,会将这个实例存入到request范围中。

    session:应用在Web项目中,Spring创建这个类实例后,会将这个的类实例存入到session域中。

    globalsession:应用在Web项目中,必须在porlet环境下才能使用,如果没有这种环境,相当于存入session域中。

    /** * 作用范围的配置 */ @Test public void demo02(){ ApplicationContext aContext = new ClassPathXmlApplicationContext("applicationContext.xml"); CustomDao bean1 = (CustomDao) aContext.getBean("customDao"); CustomDao bean2 = (CustomDao) aContext.getBean("customDao"); CustomDao bean3 = (CustomDao) aContext.getBean("customDao"); System.out.println(bean1); System.out.println(bean2); System.out.println(bean3); } //CustomDaoImpl的实例创建了 //com.nike.spring.demo02.CustomDaoImpl@63440df3 //com.nike.spring.demo02.CustomDaoImpl@63440df3 //com.nike.spring.demo02.CustomDaoImpl@63440df3 //只初始化一次,并且三个对象的地址值一致

    7.Spring属性注入(DI)

    给Bean中的属性设置值的方式有3种:

    1.构造方法方式

    2.setXxx()方法

    3.接口注入的方式

    Spring提供了2大类的属性注入方式:

    1.构造方法方式属性注入

    package com.nike.spring.demo03; public class Car { private String name; private Double price; public Car(String name, Double price) { super(); this.name = name; this.price = price; } @Override public String toString() { return "Car [name=" + name + ", price=" + price + "]"; } } <!-- 配置car类并完成属性注入(构造方法) --> <bean id="car" class="com.nike.spring.demo03.Car"> <constructor-arg name="name" value="保时捷"/> <constructor-arg name="price" value="800000"/> </bean> /** * 使用构造方法完成属性注入 */ @Test public void demo01(){ ApplicationContext aContext = new ClassPathXmlApplicationContext("applicationContext.xml"); Car car = (Car) aContext.getBean("car"); System.out.println(car); }

    2.setXxx()方法属性注入

    package com.nike.spring.demo03; /** * 使用set方法完成属性注入 * @author 猪猪 * */ public class Car2 { private String name; private Double price; public String getName() { return name; } public void setName(String name) { this.name = name; } public Double getPrice() { return price; } public void setPrice(Double price) { this.price = price; } @Override public String toString() { return "Car2 [name=" + name + ", price=" + price + "]"; } } <!-- 配置Car2类并完成属性注入(setXxx()方法) --> <bean id="car2" class="com.nike.spring.demo03.Car2"> <property name="name" value="兰博基尼"></property> <property name="price" value="140000000"></property> </bean> /** * 使用setXxx()方法完成属性注入 */ @Test public void demo02(){ ApplicationContext aContext = new ClassPathXmlApplicationContext("applicationContext.xml"); Car2 car2 = (Car2) aContext.getBean("car2"); System.out.println(car2); }
    属性注入时属性中有对象类型如何处理?
    package com.nike.spring.demo03; /** * 当类的属性时引用类型时如何完成属性注入 * @author 猪猪 * */ public class Employee { private String name; private Car2 car2; public String getName() { return name; } public void setName(String name) { this.name = name; } public Car2 getCar2() { return car2; } public void setCar2(Car2 car2) { this.car2 = car2; } @Override public String toString() { return "Employee [name=" + name + ", car2=" + car2 + "]"; } } <!-- 配置Car2类并完成属性注入(setXxx()方法) --> <bean id="car2" class="com.nike.spring.demo03.Car2"> <property name="name" value="兰博基尼"/> <property name="price" value="140000000"/> </bean> <!-- set方法注入对象类型的属性 --> <bean id="employee" class="com.nike.spring.demo03.Employee"> <!-- value使用来设置普通类型的值,ref是用来设置其他类的id或name --> <property name="name" value="工程师"/> <property name="car2" ref="car2"></property> </bean> /** * 当对象的属性是引用类型,如何使用set方法完成属性注入 */ @Test public void demo03(){ ApplicationContext aContext = new ClassPathXmlApplicationContext("applicationContext.xml"); Employee bean = (Employee) aContext.getBean("employee"); System.out.println(bean); }

    使用构造方法同样可行。

    8.p名称空间的属性注入(Spring2.5以后的版本)

    通过引入名称空间完成属性注入 写法:普通属性:p:属性名=“属性值”对象类型属性:p:属性名-ref=“属性值” xmlns:p="http://www.springframework.org/schema/P" <!-- 引入p名称空间 --> <!-- 引入p名称空间的方式完成普通属性注入 --> <bean id="car02" class="com.nike.spring.demo03.Car2" p:name="法拉利" p:price="1545665"></bean> <!-- 引入p命名空间完成引用类型的属性注入 --> <bean id="employee1" class="com.nike.spring.demo03.Employee" p:name="胡卫平" p:car2-ref="car02"></bean>

    9.SpEL的属性注入(Spring3.0以后的版本提供的)

    SpEL(Spring Expression Language)

    Spring的表达式语言

    #{SpEL}

    <!-- SpEL表达式完成属性注入 --> <bean id="car002" class="com.nike.spring.demo03.Car2"> <property name="name" value="#{'布加迪威龙'}"/> <property name="price" value="#{5489741}"/> </bean> <!-- SpEL表达式完成属性注入 --> <bean id="car002" class="com.nike.spring.demo03.Car2"> <property name="name" value="#{'布加迪威龙'}"/> <property name="price" value="#{5489741}"/> </bean> <bean id="employee01" class="com.nike.spring.demo03.Employee"> <!-- value使用来设置普通类型的值,ref是用来设置其他类的id或name --> <property name="name" value="工程师"/> <property name="car2" value="#{car002}"></property> </bean> package com.nike.spring.demo03; public class CarInfo { private String carName; public String getCarName() { return "三蹦子"; } public Double getPrice(){ return Math.random()*3000; } } <bean id="carinfo" class="com.nike.spring.demo03.CarInfo"></bean> <bean id="car0002" class="com.nike.spring.demo03.Car2"> <property name="name" value="#{carinfo.getCarName()}"/> <property name="price" value="#{carinfo.getPrice()}"/> </bean>

    10.集合类型属性的注入

    package com.nike.spring.demo04; import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.Set; import com.nike.spring.demo03.Car2; /** * 集合属性的注入 * @author 猪猪 * */ public class CollectionBean { private List<String> strs; private Integer[] ins; private List<Car2> cars; private Set<String> set; private Map<Integer,String> map; public Map<Integer, String> getMap() { return map; } public void setMap(Map<Integer, String> map) { this.map = map; } public Set<String> getSet() { return set; } public void setSet(Set<String> set) { this.set = set; } public List<Car2> getCars() { return cars; } public void setCars(List<Car2> cars) { this.cars = cars; } public Integer[] getIns() { return ins; } public void setIns(Integer[] ins) { this.ins = ins; } public List<String> getStrs() { return strs; } public void setStrs(List<String> strs) { this.strs = strs; } @Override public String toString() { return "CollectionBean [strs=" + strs + ", ins=" + Arrays.toString(ins) + ", cars=" + cars + ", set=" + set + ", map=" + map + "]"; } } <!-- Spring的集合属性注入 --> <!-- 注入列表 --> <bean id="collectionBean" class="com.nike.spring.demo04.CollectionBean"> <property name="strs"> <!-- 注入列表类型和数组类型一致 --> <list> <value>野犬</value> <value>你可</value> <value>杰神</value> <value>马克</value> </list> </property> <property name="ins"> <list> <value>1</value> <value>2</value> <value>3</value> <value>4</value> </list> </property> <property name="cars"> <list> <ref bean="car2"/> <ref bean="car02"/> <ref bean="car002"/> <ref bean="car0002"/> </list> </property> <!-- 注入set集合 --> <property name="set"> <set> <value>马云</value> <value>李彦宏</value> <value>马化腾</value> <value>雷军</value> </set> </property> <!-- 注入Map集合 --> <property name="map"> <map> <entry key="1" value="jack"></entry> <entry key="2" value="mike"></entry> <entry key="3" value="rose"></entry> <entry key="4" value="lucy"></entry> </map> </property> </bean>

    11.Spring的分模块开发

    将Spring的配置文件分成多个

    1.加载配置文件的时候加载多个

    ApplicationContext aContext = new ClassPathXmlApplicationContext("applicationContext.xml","applicationContext2.xml");

    2.在一个配置文件中引入多个配置文件

    applicationContext2.xml

    <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:p="http://www.springframework.org/schema/p" 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"> <!-- Spring的集合属性注入 --> <!-- 注入列表 --> <bean id="collectionBean" class="com.nike.spring.demo04.CollectionBean"> <property name="strs"> <!-- 注入列表类型和数组类型一致 --> <list> <value>野犬</value> <value>你可</value> <value>杰神</value> <value>马克</value> </list> </property> <property name="ins"> <list> <value>1</value> <value>2</value> <value>3</value> <value>4</value> </list> </property> <property name="cars"> <list> <ref bean="car2"/> <ref bean="car02"/> <ref bean="car002"/> <ref bean="car0002"/> </list> </property> <!-- 注入set集合 --> <property name="set"> <set> <value>马云</value> <value>李彦宏</value> <value>马化腾</value> <value>雷军</value> </set> </property> <!-- 注入Map集合 --> <property name="map"> <map> <entry key="1" value="jack"></entry> <entry key="2" value="mike"></entry> <entry key="3" value="rose"></entry> <entry key="4" value="lucy"></entry> </map> </property> </bean> </beans>

    applicationContext.xml

    <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:p="http://www.springframework.org/schema/p" 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"> <!-- Spring入门配置 --> <bean id="userDao" class="com.nike.spring.demo01.UserDaoImpl"> <property name="name" value="lisi"/> </bean> <!-- Spring bean的生命周期的配置 --> <bean name="customDao" class="com.nike.spring.demo02.CustomDaoImpl" scope="prototype" init-method="init" destroy-method="destory"></bean> <!-- 配置car类并完成属性注入(构造方法) --> <bean id="car" class="com.nike.spring.demo03.Car"> <constructor-arg name="name" value="保时捷"/> <constructor-arg name="price" value="800000"/> </bean> <!-- 配置Car2类并完成属性注入(setXxx()方法) --> <bean id="car2" class="com.nike.spring.demo03.Car2"> <property name="name" value="兰博基尼"/> <property name="price" value="140000000"/> </bean> <!-- 引入p名称空间的方式完成属性注入 --> <bean id="car02" class="com.nike.spring.demo03.Car2" p:name="法拉利" p:price="1545665"></bean> <!-- set方法注入对象类型的属性 --> <bean id="employee" class="com.nike.spring.demo03.Employee"> <!-- value使用来设置普通类型的值,ref是用来设置其他类的id或name --> <property name="name" value="工程师"/> <property name="car2" ref="car2"></property> </bean> <!-- 引入p命名空间完成引用类型的属性注入 --> <bean id="employee1" class="com.nike.spring.demo03.Employee" p:name="胡卫平" p:car2-ref="car02"></bean> <!-- SpEL表达式完成属性注入 --> <bean id="car002" class="com.nike.spring.demo03.Car2"> <property name="name" value="#{'布加迪威龙'}"/> <property name="price" value="#{5489741}"/> </bean> <bean id="employee01" class="com.nike.spring.demo03.Employee"> <!-- value使用来设置普通类型的值,ref是用来设置其他类的id或name --> <property name="name" value="工程师"/> <property name="car2" value="#{car002}"></property> </bean> <bean id="carinfo" class="com.nike.spring.demo03.CarInfo"></bean> <bean id="car0002" class="com.nike.spring.demo03.Car2"> <property name="name" value="#{carinfo.getCarName()}"/> <property name="price" value="#{carinfo.getPrice()}"/> </bean> <!-- 使用import标签引入其他配置文件 --> <import resource="applicationContext2.xml"/> </beans>
    最新回复(0)