Spring=Spring基础详解

阅读: 评论:0

Spring=Spring基础详解

Spring=Spring基础详解

spring官网:/

一.Spring概述

Spring是分层的 Java SE/EE应用 full-stack(全栈) 轻量级开源框架

Spring的核心是 IOC(Inverse Of Control:控制反转)和 AOP(Aspect Oriented Programming:面向切面编程)

Spring一个全栈应用框架, 提供了表现层 Spring MVC 和持久层 Spring JDBC 以及业务层事务管理等众多应用技术

Spring还能整合开源世界众多著名的第三方框架和类库,逐渐成为使用最多的 Java EE 企业应用开源框架

Spring官网:/

(1)发展历程:

* EJB1997 年,IBM提出了EJB 的思想1998 年,SUN制定开发标准规范 EJB1.01999 年,EJB1.1 发布2001 年,EJB2.0 发布2003 年,EJB2.1 发布2006 年,EJB3.0 发布* SpringRod Johnson( Spring 之父)改变Java世界的大师级人物2002年编著《Expert one on one J2EE design and development》	指出了JavaEE和EJB组件框架中的存在的一些主要缺陷;提出普通java类依赖注入更为简单的解决方案。2004年编著《Expert one-on-one J2EE Development without EJB》阐述了JavaEE开发时不使用EJB的解决方式(Spring 雏形)同年4月spring1.0诞生2006年10月,发布 Spring2.02009年12月,发布 Spring3.02013年12月,发布 Spring4.02017年9月, 发布最新 Spring5.0 通用版(GA)

(2)Spring开发优势:

1. 方便解耦,简化开发通过Spring提供的 IOC 容器,可以将对象间的依赖关系交由 Spring 进行控制,避免硬编码所造成的过度耦合。  用户也不必再为单例模式类、属性文件解析等这些很底层的需求编写代码,可以更专注于上层的应用。2. AOP编程的支持通过Spring的AOP功能,方便进行面向切面编程,许多不容易用传统 OOP 实现的功能可以通过 AOP 轻松实现。3. 声明式事务的支持可以将我们从单调烦闷的事务管理代码中解脱出来,通过声明式方式灵活的进行事务管理,提高开发效率和质量。4. 方便程序的测试可以用非容器依赖的编程方式进行几乎所有的测试工作,测试不再是昂贵的操作,而是随手可做的事情。5. 方便集成各种优秀框架Spring对各种优秀框架(Struts、Hibernate、Hessian、Quartz等)的支持。6. 降低JavaEE API的使用难度Spring对JavaEEAPI(如JDBC、JavaMail、RPC等)进行了薄薄的封装层,使这些 API 的使用难度大为降低。7. Java源码经典学习范例Spring的源代码设计精妙、结构清晰、匠心独用,处处体现着大师对Java 设计模式灵活运用以及对 Java技术的高深造诣。它的源代码无意是 Java 技术的最佳实践的范例。

(3)Spring体系结构:

 

二.初识IOC(控制反转)

(1)介绍:

控制反转(Inverse Of Control)不是什么技术,而是一种设计思想。它的目的是指导我们设计出更加松耦合的程序。

控制:在java中指的是对象的控制权限(创建、销毁)

反转:指的是对象控制权由原来 由开发者在类中手动控制 反转到 由Spring容器控制

比如:

* 原来我们需要一个对象,需要自己手动new出来UserServletUserService us = new UserServiceImpl();* 学习了spring之后,需要一个对象,从spring的ioc容器获取		UserServletUserService us = spring的IOC容器.getBean("userService");* IOC的核心思想:松耦合

需求:实现service层和dao层代码解耦合

(2)案例

新建idea项目:

项目完毕:

统一进行设置:

  1. 创建Maven的java模块:

导入maven 的jar包

<!--依赖管理-->
<dependencies><!--dom4j--><dependency><groupId>dom4j</groupId><artifactId>dom4j</artifactId><version>1.6.1</version></dependency><!--xpath--><dependency><groupId>jaxen</groupId><artifactId>jaxen</artifactId><version>1.1.6</version></dependency><!--junit--><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version></dependency>
</dependencies>

(2)实现方案比较:

==版本1==原始版本

编写UserDao接口和实现类:快捷键alt+insert

编写UserService接口和实现类:

编写UserTest

问题总结;

==版本2==工厂解耦

我们需要在项目中 定义BeanFactory + xml解析,实现各层代码之间解耦合

编写l

编写BeanFactory

public class BeanFactory {public static Object getBean(String id) {Object object = null;try {// 1.通过类加载器读取 lInputStream in = ClassLoader().getResourceAsStream(&#l");// 2.创建dom4j核心解析器对象SAXReader saxReader = new SAXReader();Document document = ad(in);// 3.编写xpath表达式// String xpath = "//bean[@id='userDao']";String xpath = "//bean[@id='" + id + "']";// 4.获取指定id的标签对象Element element = (Element) document.selectSingleNode(xpath);// 5.获取全限定名String className = element.attributeValue("class");// 6.通过反射创建对象实例object = Class.forName(className).newInstance();} catch (Exception e) {e.printStackTrace();}// 7.返回对象实例return object;}
}

修改UserServiceImpl

问题:

==版本3== 工厂优化:

使用单例模式:

修改BeanFactory

public class BeanFactory {// 声明存储对象的容器(map集合)private static Map<String, Object> ioc = new HashMap<>();// 静态代码块,初始化ioc容器static {String id = null;String className = null;Object object = null;try {// 1.通过类加载器读取 lInputStream in = ClassLoader().getResourceAsStream(&#l");// 2.创建dom4j核心解析器对象SAXReader saxReader = new SAXReader();Document document = ad(in);// 3.编写xpath表达式String xpath = "//bean";// 4.获取所有的bean标签对象List<Element> list = document.selectNodes(xpath);// 5.遍历集合,创建对象实例,设置到ioc容器中for (Element element : list) {id = element.attributeValue("id");className = element.attributeValue("class");object = Class.forName(className).newInstance();// 设置到map集合ioc.put(id, object);}} catch (Exception e) {e.printStackTrace();}}// 从ioc容器中获取指定id的对象实例public static Object getBean(String id) {(id);}
}

总结

对象的创建由原来的 使用 new关键字在类中主动创建 变成了 从工厂中获取, 而对象的创建过程由工厂内部来实现, 而这个工厂就是 Spring的IOC容器, 也就是以后我们的对象不再自己创建,而是直接向Spring要, 这种思想就是IOC

ioc目的:松耦合...,你可以简单的认为就是一个map集合(ioc容器)

三.Spring入门:

流程图:

代码实现

创建maven的java模块:

导入spring相关坐标:

<!--依赖管理-->
<dependencies><!--spring的核心坐标--><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>5.1.5.RELEASE</version></dependency><!--junit--><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version></dependency>
</dependencies>

编写UserDao接口和实现类:

创建spring的核心配置文件,导入约束

官方推荐&#l

编写bean标签:(id,class)

测试:模拟service层

public class UserTest {// spring的快速入门@Testpublic void test01() throws Exception {// 1.通过spring的api读取配置文件ClassPathXmlApplicationContext app = new ClassPathXmlApplicationContext(&#l");// 2.获取指定id的对象实例UserDao userDao = (UserDao) Bean("userDao");userDao.save();}
}

 

四/Spring相关API

spring的api体系非常的庞大,我们先介绍核心的内容

(1)两个接口
 

* BeanFactory介绍:这是IOC容器的顶级接口 它定义了IOC的最基础的功能, 但是其功能比较简单,一般面向Spring自身使用特点:在第一次使用到某个Bean时(调用getBean()),才对该Bean进行加载实例化[用的时候再创建]懒汉设计* ApplicationContext介绍:这是在BeanFactory基础上衍生出的接口,它扩展了BeanFactory的功能,一般面向程序员使用特点:在容器启动时,一次性创建并加载了所有的Bean  [初始化的时候全创建好]恶汉设计* 小结:上面两种方式创建的对象都是单例, 只是创建对象的时机不同

 

(2)三个实现类:

* ClassPathXmlApplicationContext功能:读取类路径(classpath)下的xml配置文件* FileSystemXmlApplicationContext功能:读取本地磁盘下的xml配置文件* AnnotationConfigApplicationContext功能:读取java配置类加载配置

(3)一个方法:

* public Object getBean(String name) throws BeansException;功能:通过指定id获取对象的实例,需要手动强转* public <T> T getBean(Class<T> requiredType);功能:通过指定类型获取对象的实例,不需要强转* public <T> T getBean(String name, Class<T> requiredType);功能:通过指定id和类型获取对象的实例
    // getBean方法介绍@Testpublic void test02() throws Exception {// 1.通过spring的api读取配置文件ApplicationContext app = new ClassPathXmlApplicationContext(&#l");// 方式一: 通过指定id获取对象的实例,需要手动强转/*UserDao userDao1 = (UserDao) Bean("userDao");userDao1.save();*/// 方式二:通过指定(接口)类型获取对象的实例,不需要强转/*缺点:如果同一个接口类型下有多个对象实例,会报错的...UserDao userDao2 = Bean(UserDao.class);userDao2.save();*/// 方式三:通过指定id和类型获取对象的实例UserDao userDao3 = Bean("userDao", UserDao.class);userDao3.save();}

五.Spring配置文件

(1)Bean标签基本配置:

基本配置:

    <!--bean标签的二个基本属性id:在ioc容器的唯一标识class:创建对象实例的全限定名--><bean id="userDao" class="com.wsl.dao.impl.UserDaoImpl"></bean>

作用范围:

    <!--bean标签还有一个属性scope属性:声明此对象的作用范围singleton:单例对象(默认)何时创建?ioc容器初始化时,创建对象对象运行?只要ioc容器在,对象就一直活着....何时销毁?ioc容器关闭时,销毁对象prototype:多例对象何时创建?在调用getBean()方法时,创建对象运行?一直使用就一直活着何时销毁?当对象不再使用后,根据JVM GC机制垃圾回收--><bean id="userDao" class="com.wsl.dao.impl.UserDaoImpl" scope="prototype"></bean>

生命周期:

 

(2)Spring创建对象实例的三种方式:

  ==无参构造方法实例化:使用最多:

在企业开发中,所有的类必须提供无参构造方法:

==工程静态方法实例化

依赖的jar包中有个A类,A类中有个静态方法m1,m1方法的返回值是一个B对象。如果我们频繁使用B对象,此时我们可以将B对象的创建权交给spring的IOC容器,以后我们在使用B对象时,无需调用A类中的m1方法,直接从IOC容器获得。

/*工厂静态方法实例化对象*/
public class StaticFactoryBean {public static UserDao createUserDao() {return new UserDaoImpl();}// 传统方式,自己通过工厂获取对象...public static void main(String[] args) {UserDao userDao = ateUserDao();}
}

工厂普通方法实例化:

依赖的jar包中有个A类,A类中有个普通方法m1,m1方法的返回值是一个B对象。如果我们频繁使用B对象,此时我们可以将B对象的创建权交给spring的IOC容器,以后我们在使用B对象时,无需调用A类中的m1方法,直接从IOC容器获得。

/*工厂普通方法实例化对象*/
public class DynamicFactoryBean {public UserDao createUserDao() {return new UserDaoImpl();}// 传统方式,自己通过工厂获取对象...public static void main(String[] args) {// 1.创建工厂对象DynamicFactoryBean dynamicFactoryBean = new DynamicFactoryBean();// 2.创建UserDao对象UserDao userDao = ateUserDao();}
}

 

(3)Bean依赖注入:

依赖注入(Dependency Injection, DI) 它是 Spring 框架核心 IOC 的具体实现

其实就是给对象中的属性赋值的过程,通过spring完成依赖注入

案例环境搭建:

创建maven的java模块:

创建UserDao,UserService等文件

编写Spring的核心配置文件:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns=""xmlns:xsi=""xsi:schemaLocation="://www.springframework/schema/beans/spring-beans.xsd"><!--将userDao交给ioc容器--><bean id="userDao" class="cn.wsl.dao.impl.UserDaoImpl"></bean><!--将userService交给ioc容器--><bean id="userService" class="cn.wsl.service.impl.UserServiceImpl"></bean>
</beans>

测试,报错:

由于service依赖了dao,但是缺少依赖注入环境

public class UserTest {@Testpublic void test01() throws Exception {// 1.加载spring配置文件ClassPathXmlApplicationContext app = new ClassPathXmlApplicationContext(&#l");// 2.获取service对象实例UserService userService = Bean(UserService.class);userService.save();}

 

(4)Bean依赖注入方式:

===构造方法:

public class UserServiceImpl implements UserService {private UserDao userDao;public UserServiceImpl(UserDao userDao) {this.userDao = userDao;}@Overridepublic void save() {userDao.save();}
}
    <!--构造方法注入: <constructor-arg> 子标签版本一:name:构造方法参数名称value:简单数据类型(String、int、)ref:引用数据类型(从ioc容器中获取的对象)版本二:index:构造方法参数索引type:该索引对应的java类型(全限定名)value:简单数据类型(String、int、)ref:引用数据类型(从ioc容器中获取的对象)--><bean id="userService" class="cn.wsl.service.impl.UserServiceImpl"><constructor-arg name="userDao" ref="userDao"></constructor-arg><!--<constructor-arg index="0" type="cn.wsl.dao.UserDao"  ref="userDao"></constructor-arg>--></bean>

==set方法:项目中使用

public class UserServiceImpl implements UserService {private UserDao userDao;public void setUserDao(UserDao userDao) {this.userDao = userDao;}@Overridepublic void save() {userDao.save();}}
    <!--将userDao交给ioc容器--><bean id="userDao" class="cn.wsl.dao.impl.UserDaoImpl"></bean>  <!--set方法注入:<property> 子标签name:set方法的属性名  setUserDao()  -> UserDao -> userDaovalue:简单数据类型(String、int、)ref:引用数据类型(从ioc容器中获取的对象)--><bean id="userService" class="cn.wsl.service.impl.UserServiceImpl"><property name="userDao" ref="userDao"></property></bean>

==P 命名空间注入

P命名空间注入底层(本质)使用的也是set方法注入,只是在上着的基础上进行简化

1)导入P命名空间约束

2)使用P命名空间完成注入

 

(5)Bean依赖注入的数据类型:

 简单数据类型

引用数据类型:见上

集合数据类型

单列集合:list,set,array

public class UserDaoImpl implements UserDao {private List<Object> list;private Set<Object> set;private Object[] array;public void setList(List<Object> list) {this.list = list;}public void setSet(Set<Object> set) {this.set = set;}public void setArray(Object[] array) {this.array = array;}@Overridepublic void save() {System.out.println("UserDao保存了....");System.out.println(list);System.out.println(set);System.out.String(array));}
}
   <!--di 注入单列集合类型需要在 <property>标签中list集合  使用子标签  <list><value> 简单数据类型<ref>   引用数据类型(对象在ioc容器中)set集合    使用子标签 <set><value> 简单数据类型<ref>   引用数据类型(对象在ioc容器中)array数组   使用子标签<array><value> 简单数据类型<ref>   引用数据类型(对象在ioc容器中)--><bean id="userDao" class="cn.wsl.dao.impl.UserDaoImpl"><property name="list"><list><value>石榴</value><value>秋香</value><ref bean="user"></ref></list></property><property name="set"><set><value>秋奎</value><value>马梅</value><ref bean="user"></ref></set></property><property name="array"><array><value>国峰</value><value>小羊</value><ref bean="user"></ref></array></property></bean>

双列集合

map,properties

public class UserDaoImpl implements UserDao {private Map<String, Object> map;private Properties props;public void setMap(Map<String, Object> map) {this.map = map;}public void setProps(Properties props) {this.props = props;}@Overridepublic void save() {System.out.println("UserDao保存了....");System.out.println(map);System.out.println(props);}}
<!--di 注入双列集合类型需要在 <property>标签中map集合 使用子标签<map><entry key="" value="简单数据类型"  |  value-ref="引用数据类型(对象ioc中)"  ></entry>properties集合 使用子标签 <props><prop key="" >value</prop>-->
<bean id="userDao" class="cn.wsl.dao.impl.UserDaoImpl"><property name="map"><map><entry key="k1" value="v1"></entry><entry key="k2" value="v2"></entry><entry key="u1" value-ref="user"></entry></map></property><property name="props"><props><prop key="k1" >v1</prop><prop key="k2" >v2</prop><prop key="k3" >v3</prop></props></property>
</bean>

(6)配置文件模块化

实际开发中,Spring的配置内容非常多,这就导致Spring配置很繁杂且体积很大,所以,可以将部分配置拆解到其他配置文件中,也就是所谓的配置文件模块化。

==并列加载:

==主从配置:

注意:

1.在同一个xml中 bean标签的 id不能重复....

2.在多个模块中的xml中,bean标签id重复虽然不会报错,但是后加载的会覆盖先加载的....

在开发中绝不允许出现重名的id

 

学习资源:源码解读

死磕Spring

 

 

本文发布于:2024-01-31 01:55:31,感谢您对本站的认可!

本文链接:https://www.4u4v.net/it/170663733424501.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:详解   基础   Spring
留言与评论(共有 0 条评论)
   
验证码:

Copyright ©2019-2022 Comsenz Inc.Powered by ©

网站地图1 网站地图2 网站地图3 网站地图4 网站地图5 网站地图6 网站地图7 网站地图8 网站地图9 网站地图10 网站地图11 网站地图12 网站地图13 网站地图14 网站地图15 网站地图16 网站地图17 网站地图18 网站地图19 网站地图20 网站地图21 网站地图22/a> 网站地图23