摘要:简单来说,是一个轻量级的控制反转和面向切面的容器框架。变成的支持提供面向切面编程,可以方便的实现对程序进行权限拦截,运行监控等功能。用于反射创建对象,默认情况下调用无参构造函数。指定对象的作用范围。
1.Spring介绍 1.1 Spring概述
Spring是一个开源框架,Spring是于2003 年兴起的一个轻量级的Java 开发框架,由Rod Johnson 在其著作Expert One-On-One J2EE Development and Design中阐述的部分理念和原型衍生而来。它是为了解决企业应用开发的复杂性而创建的。Spring使用基本的JavaBean来完成以前只可能由EJB完成的事情。然而,Spring的用途不仅限于服务器端的开发。从简单性、可测试性和松耦合的角度而言,任何Java应用都可以从Spring中受益。简单来说,Spring是一个轻量级的控制反转(IoC)和面向切面(AOP)的容器框架。
1.2 Spring好处
方便解耦,简化开发
Spring就是一个大工厂,专门负责生成Bean,可以将所有对象创建和依赖关系维护由Spring管理。通过Spring提供的IoC容器,可以将对象间的依赖关系交由Spring进行控制,避免硬编码所造成的过度程序耦合。用户也不必再为单例模式类、属性文件解析等这些很底层的需求编写代码,可以更专注于上层的应用。
AOP变成的支持
Spring提供面向切面编程,可以方便的实现对程序进行权限拦截,运行监控等功能。通过Spring的AOP功能,方便进行面向切面的编程,许多不容易用传统OOP实现的功能可以通过AOP轻松应付。
声明式事务的支持
只需要通过配置就可以完成对事务的管理,而无需手动编程
方便程序的测试
Spring对Junit4支持,可以通过注解方便的测试Spring程序
方便集成各种优秀框架
Spring不排斥各种优秀的开源框架,其内部提供了对各种优秀框架的支持,如Struts、Hibernate、Mybatis、Quartz等
降低JavaEE API的使用难度
对JavaEE开发中一些难用的API(JDBC、JavaMail、远程调用等),都提供了封装,使这些API应用难度大大降低
Java源码是经典学习范例
Spring的源代码设计精妙、结构清晰、匠心独用,处处体现着大师对Java设计模式灵活运用以及对Java技术的高深造诣。它的源代码无意是Java技术的最佳实践的范例。
1.3 Spring结构体系Spring框架是一个分层架构,它包含一系列的功能要素并被分为大约20个模块。这些模块分为Core Container、DataAccess/Integration、Web、AOP、Instrumentation和测试部分。如下图所示:
1.4 在项目中的架构web层:Struts,SpringMVC
dao层:Hibernate,Mybatis
1.5 程序的耦合和解耦
程序的耦合
我们开发种,会写很多的类,而有些类之间不可避免地产生依赖关系,这种依赖关系称为耦合。有些依赖是必须的,有些依赖关系可以通过优化代码来解除。比如:
</>复制代码
/**
* 客户的业务层实现类
*/
public class CustomerServiceImpl implements ICustomerService {
private ICustomerDao customerDao = new CustomerDaoImpl();
}
上面的代码表示:业务调用持久层,并且此时业务再依赖持久层的接口和实现类。如果此时没有持久层实现类,编译将不能通过。这种依赖关系就是我们可以通过优化代码解决的。
再比如:下面的代码种,我们的类依赖MySQL的具体驱动类,如果这狮虎更换了数据库品牌,我们需要改源码来修修改数据库驱动,这显然不是我们想要的。
</>复制代码
public class JdbcDemo1 {
/**
* JDBC操作数据库的基本入门中存在什么问题?
* 导致驱动注册两次是个问题,但不是严重的。
* 严重的问题:是当前类和mysql的驱动类有很强的依赖关系。
* 当我们没有驱动类的时候,连编译都不让。
* 那这种依赖关系,就叫做程序的耦合
*
* 我们在开发中,理想的状态应该是:
* 我们应该尽力达到的:编译时不依赖,运行时才依赖。
*
* @param args
* @throws Exception
*/
public static void main(String[] args) throws Exception {
//1.注册驱动
//DriverManager.registerDriver(new com.mysql.jdbc.Driver());
Class.forName("com.mysql.jdbc.Driver");
//2.获取连接
//3.获取预处理sql语句对象
//4.获取结果集
//5.遍历结果集
}
解决程序耦合的思路
在JDBC种是通过反射来注册驱动的,代码如下:
</>复制代码
Clas.forName("com.mysql.jdbc.Driver");
这时的好处是,我们类中不再依赖具体的驱动类,此时就算删除MySQL的驱动jar包,依然可以编译。但是没有驱动类,所以不能运行。
不过,此处也有一个问题,就是我们反射类对象的全限定类名字符串是在Java类中写死的,一旦要改还是徐娅修改源码。为了解决这个问题,使用配置文件配置。
工厂模式解耦
在实际开发过程总我们把所有的dao和service和action对象使用配置文件配置起来,当启动服务器应用加载的时候,通过读取配置文件,把这些对象创建出来并存起来。在接下来使用的时候,直接拿就好了。
控制反转---Inversion Of Control
上面解耦的思路有两个问题
创建的对象存储在哪里?由于我们是很多对象,肯定要找个集合来存储,这时候有Map和List供选择。到底是选择Map还是List就看我们有没有查找的需求。有查找的需求就选Map。所以我们的答案是:在应用加载时,创建一个Map,用于存放action,service和dao对象。
还是没解释什么是工厂?工厂就是负责给我们从容器中获取指定对象的类。这时候获取对象的方式发生了改变。以前,我们在获取对象的时候,都是采用new的方式,是主动的。
现在,我么获取对象的时候,同时跟工厂要,有工厂为我们查找或者创建对象。是被动的。这种被动接收的方式获取对象的思想就是控制反转,他是Spring框架的核心之一。其作用只有一个:降低计算机程序的耦合。
2. Spring快速入门使用spring的IOC解决程序耦合
2.1 编写流程下载Spring开发包
导入Spring的jar包
配置Spring的核心xml文件
在程序中读取Spring的配置文件来获取Bean【Bean其实就是一个new好的对象】
2.2 下载地址这里下载4.2.4版本
地址:http://repo.spring.io/release...
官网:spring.io 官网改版后,下载链接需要在对应的GitHub上找
2.3 Spring的核心jar包spring-core-4.2.4.RELEASE.jar包含Spring框架基本的核心工具类,Spring其他组件都要使用到这个包里得嘞,是其他组件的基本核心。
spring-beans-4.2.4.RELEASE.jar所有应用都要用到的,它包含访问配置文件、创建和管理bean
以及进行Inversion of Control(IoC) / Dependency Injection(DI)操作相关的所有类。
spring-context-4.2.4.RELEASE.jarSpring提供在基础IoC功能上的扩展服务,此外还提供许多企业级服务的支持,
如邮件服务、任务调度、JNDI定位、EJB集成、远程访问、缓存以及各种视图层框架的封装等。
spring-expression-4.2.4.RELEASE.jarSpring表达式语言。
com.springsource.org.apache.commons.logging-1.1.1.jar第三方的主要用于处理日志。
2.4 Spring入门案例
准备项目需要得jar包
spring-framework-4.2.4.RELEASE-dist.zip 【Spring的核心包】
spring-framework-4.2.4.RELEASE-dependencies.zip 【Spring的依赖包】
创建Project,导入Spring的jar包
在src路径下创建applicationContext.xml文件
导入约束
把资源交给Spring管理,在xml文件中配置User
</>复制代码
测试
</>复制代码
package com.itzhouq.domain;
public class User {
public void run() {
System.out.println("run");
}
}
</>复制代码
package com.itzhouq.test;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.itzhouq.domain.User;
public class UserTeset {
@Test
public void test() {//自己new的对象
User user = new User();
user.run();
}
@Test
public void test2() {//spring的ioc创建对象
//加载配置文件 src/classes类路径
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
//找Spring要对象
User user = (User) context.getBean("user");
user.run();
}
}
3. Spring基于XML的IOC细节
3.1 IOC中bean标签和管理对象细节
3.1.1 配置文件bean标签
作用
用于配置对象让Spring来创建的。默认情况下它调用的是类中的无参构造函数。如果没有无参构造函数则不能创建成功。
属性
id:给对象在容器中提供一个唯一标识,用于获取对象
class:指定类的全限定名。用于反射创建对象,默认情况下调用无参构造函数。
scope:指定对象的作用范围。
init-method:指定类中的初始化方法名称。
destroy-method:指定类中销毁方法名称。
import:导入外部配置文件,resource----外部配置文件的地址。
3.1.2 scope属性:范围(重点)</>复制代码
singleton: 单实例 默认值
如果是单实例,配置文件文件只要一加载 就会创建对象 放在spring容器 (map
当所有人过来问spring容器要的时候(getBean),所用人用的都是同一个对象
prototype: 多实例
如果是多实例,配置文件加载,不创建对象
当每个人过来getbean的时候,getbean一次创建一次 放在容器中
什么时候用默认值singleton(单实例)? 什么时候用prototype(多实例)?
action: prototype
service/dao: singleton
request:web项目中Spring创建一个Bean对象,将对象存入到request域中
session:web项目中Spring创建一个Bean对象,将对象存入到session域中。
globalSession:web项目中,应用在Portlet环境,如果没有Portlet环境那么globalSession相当于session。
3.1.3 bean的作用范围和生命周期
单例对象:scope="singleton"
一个应用只有一个对象的实例。它的作用范围就是整个引用。
生命周期:
对象出生:当应用加载,创建容器时,对象就被创建了。
对象活着:只要容器在,对象一直活着。
对象死亡:当应用卸载,销毁容器时,对象就被销毁了。
多例对象:scope="prototype"
每次访问对象时,都会重新创建对象实例。
生命周期:
对象出生:当使用对象时,创建新的对象实例。
对象活着:只要对象在使用中,就一直活着。
对象死亡:当对象长时间不用时,被java的垃圾回收器回收了。
3.1.4 示例化Bean的三种方式
无参构造方式(最常用)
</>复制代码
@Test//测试bean的三种创建方式------无参构造方式
public void test3() {
//加载配置文件 src/classes类路径
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
//找Spring要对象
User user = (User) context.getBean("user");
user.run();
}
静态工厂方式(了解)
条件:需要有一个工厂类,在这个工厂类中还需要一个静态方法
</>复制代码
package com.itzhouq.utils;
import com.itzhouq.domain.User;
public class BeanFactory {
public static User createUser() {
return new User();
}
}
</>复制代码
测试
</>复制代码
@Test//测试bean的三种创建方式------静态工厂方式
public void test4() {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
User user1 = (User) context.getBean("user");
System.out.println(user1);//com.itzhouq.domain.User@5f3a4b84
User user2 = (User) context.getBean("user");
System.out.println(user2);//com.itzhouq.domain.User@5f3a4b84
}
实例工厂方式(了解)
条件:需要一个工厂类在这个工厂类中需要一个普通方法
</>复制代码
package com.itzhouq.utils;
import com.itzhouq.domain.User;
public class BeanFactory {
// public static User createUser() {
// return new User();
// }
//普通方法----实例工厂
public User createUser() {
return new User();
}
}
配置文件
</>复制代码
测试
</>复制代码
@Test//测试bean的三种创建方式------实例工厂方式
public void test5() {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
User user1 = (User) context.getBean("user");
System.out.println(user1);//com.itzhouq.domain.User@5f3a4b84
User user2 = (User) context.getBean("user");
System.out.println(user2);//com.itzhouq.domain.User@5f3a4b84
}
3.2 加载Spring容器的三种方式
类路径获得配置文件
文件系统路径获得配置文件
使用BeanFactory(了解)
</>复制代码
public class Lession01 {
@Test
public void test01(){
//Spring容器加载有3种方式
//第一种:ClassPathXmlApplicationContext ClassPath类路径加载:指的就是classes路径
//最常用,Spring的配置文件以后就放在src路径下
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
//第二种方式:文件系统路径获得配置文件【绝对路径】
ApplicationContext context = new FileSystemXmlApplicationContext("E:workspacesIdeaProjectSpring-day02-gyfsrceans.xml");
IUserService user = (IUserService) context.getBean("userService");
user.add();
//第三种方式:
String path = "E:workspacesIdeaProjectSpring-day02-gyfsrceans.xml";
BeanFactory factory = new XmlBeanFactory(new FileSystemResource(path));
IUserService user1 = (IUserService) factory.getBean("userService");
user1.add();
}
}
Spring内部创建对象的原理
</>复制代码
1. 解析xml文件,获得类名,id,属性
2. 通过反射,用类型创建对象
3. 给创建的对象赋值
3.3 BeanFactory和ApplicationContext对比
BeanFactory采用延迟加载,第一次getBean时才会初始化Bean
ApplicationContext是对BeanFactory扩展,提供了更多功能
国际化处理
事件传递
Bean自动装配
各种不同应用的Context实现
3. 4 Spring的依赖注入DIDI属性的依赖注入,是Spring框架核心IoC的具体实现方式。Spring在通过Ioc创建对象的时候,如果这个对象还有属性,就一并赋值进去,而不用我们自己去获取。
入门举例:
创建一个接口Car
</>复制代码
package com.itzhouq.service;
public interface Car {
public void run();
}
创建实现类CarImpl
</>复制代码
package com.itzhouq.serviceImpl;
import com.itzhouq.service.Car;
public class CarImpl implements Car {
private String name;
public void setName(String name) {
this.name = name;
}
@Override
public void run() {
System.out.println(name+"车跑起来了.....");
}
}
测试
</>复制代码
package com.itzhouq.test;
import org.junit.Test;
import com.itzhouq.serviceImpl.CarImpl;
public class CarTest {
@Test//自己new对象 自己属性赋值的方式
public void test() {
CarImpl car = new CarImpl();
car.setName("qq");
car.run();//qq车跑起来了.....
}
}
入门举例2:依赖注入的方式
配置文件:
</>复制代码
测试
</>复制代码
@Test //Spring的IOC
public void test2() {
ApplicationContext context = new ClassPathXmlApplicationContext("ApplicationContext.xml");
Car car = (Car)context.getBean("car");
//把这个对象的属性也在创建的时候给顺便赋值了-----DI
car.run();//兰博基尼车跑起来了.....
}
依赖注入的方式
构造函数注入(了解)
set方法注入(掌握)
使用p名称空间注入数据(本质还是调用set方法)(了解)
注入集合属性
3.4.1 构造器注入方式条件:需要有有参构造方法
给CarImpl设置有参构造
</>复制代码
package com.itzhouq.serviceImpl;
import com.itzhouq.service.Car;
public class CarImpl implements Car {
private String name;
private double price;
public void setName(String name) {
this.name = name;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
public String getName() {
return name;
}
public CarImpl() {}
//有参的构造方法----DI的构造器注入方式
public CarImpl(String name, double price) {
super();
this.name = name;
this.price = price;
}
@Override
public void run() {
System.out.println("价值"+price+"的"+name+"车跑起来了.....");
}
}
配置文件
</>复制代码
测试
</>复制代码
@Test //Spring的DI注入方式----构造器的注入方式(了解)
public void test3() {
ApplicationContext context = new ClassPathXmlApplicationContext("ApplicationContext.xml");
Car car = (Car)context.getBean("car");
car.run();//价值1000000.0的BMW车跑起来了.....
}
3.4.2 set方式注入
写一个Person接口
</>复制代码
package com.itzhouq.service;
public interface Person {
}
PersonImpl实现接口Person,设置set方法
</>复制代码
package com.itzhouq.serviceImpl;
import com.itzhouq.service.Car;
import com.itzhouq.service.Person;
public class PersonImpl implements Person {
private String name;
private Car car;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Car getCar() {
return car;
}
public void setCar(Car car) {
this.car = car;
}
@Override
public String toString() {
return "PersonImpl [name=" + name + ", car=" + car + "]";
}
}
配置文件
</>复制代码
测试
</>复制代码
@Test //Spring的DI注入方式----set的注入方式(了解)
public void test4() {
ApplicationContext context = new ClassPathXmlApplicationContext("ApplicationContext.xml");
Person person = (Person) context.getBean("person");
System.out.println(person);
//PersonImpl [name=jack, car=CarImpl [name=BMW, price=1000000.0]]
}
3.4.3 使用p名称空间注入数据(知道就OK)
此种方式是通过在xml中导入p名称空间,使用p:propertyName来注入数据,它的本质仍然是调用类中的set方法实现注入功能。
配置文件
3.4.4 注入集合属性</>复制代码
顾名思义,就是给类中的集合成员传值,它用的也是set方法注入的方式,只不过变量的数据类型都是集合。我们这里介绍注入数组,List,Set,Map,Properties。
创建一个类CollBean,设置set方法
</>复制代码
package com.itzhouq.domain;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Properties;
public class CollBean {
private String[] ss;
private List ll;
private Map mm;
private Properties properties;
public String[] getSs() {
return ss;
}
public void setSs(String[] ss) {
this.ss = ss;
}
public List getLl() {
return ll;
}
public void setLl(List ll) {
this.ll = ll;
}
public Map getMm() {
return mm;
}
public void setMm(Map mm) {
this.mm = mm;
}
public Properties getProperties() {
return properties;
}
public void setProperties(Properties properties) {
this.properties = properties;
}
@Override
public String toString() {
return "CollBean [ss=" + Arrays.toString(ss) + ", ll=" + ll + ", mm=" + mm + ", properties=" + properties + "]";
}
}
配置文件
</>复制代码
测试
</>复制代码
package com.itzhouq.test;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.itzhouq.domain.CollBean;
public class CollBeanTest {
@Test
public void test() {
ApplicationContext context = new ClassPathXmlApplicationContext("ApplicationContext.xml");
CollBean cb = (CollBean) context.getBean("collBean");
System.out.println(cb);
/*
* CollBean [ss=[aaa, bbb, ccc],
* ll=[111, 222, CarImpl [name=BMW, price=1000000.0]],
* mm={k1=AAA, k2=BBB, k3=CarImpl [name=BMW, price=1000000.0]},
* properties={hibernate.password=1234, hibernate.username=root}]
*/
}
}
4.使用案例
需求分析:从service层调用dao层,将数据存储到数据库,存储数据的过程使用syso模拟一下就可以。
创建工程,导入需要的jar包,建包如下:
创建dao层和dao实现层
</>复制代码
package com.itzhouq.dao;
public interface UserDao {
void save();
}
</>复制代码
package com.itzhouq.daoImpl;
import com.itzhouq.dao.UserDao;
public class UserDaoImpl implements UserDao{
@Override
public void save() {
System.out.println("操作数据库,保存用户的数据");
}
}
创建Service层和实现层
</>复制代码
package com.itzhouq.service;
public interface UserService {
public void save();
}
</>复制代码
package com.itzhouq.serviceImpl;
import com.itzhouq.dao.UserDao;
import com.itzhouq.daoImpl.UserDaoImpl;
import com.itzhouq.service.UserService;
public class UserServiceImpl implements UserService {
private String name;
private UserDao userDao;
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
public void setName(String name) {
this.name = name;
}
@Override
public void save() {
System.out.println(name);
//调用dao
userDao.save();
}
}
给UserDaoImpl一个UserDao属性
配置文件
</>复制代码
测试
</>复制代码
@Test //使用Spring的IOC+DI来实现对象的创建和赋值
public void test() {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
UserService userService = (UserService) context.getBean("UserService");
userService.save();
//要开始访问dao了
//操作数据库,保存用户的数据
}
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/74363.html
摘要:哪吒社区技能树打卡打卡贴函数式接口简介领域优质创作者哪吒公众号作者架构师奋斗者扫描主页左侧二维码,加入群聊,一起学习一起进步欢迎点赞收藏留言前情提要无意间听到领导们的谈话,现在公司的现状是码农太多,但能独立带队的人太少,简而言之,不缺干 ? 哪吒社区Java技能树打卡 【打卡贴 day2...
摘要:现在的分片策略是上海深圳分别建库,每个库都存各自交易所的两支股票的,且按照月分表。五配置分片策略数据库分片策略在这个实例中,数据库的分库就是根据上海和深圳来分的,在中是单键分片。 由于当当发布了最新的Sharding-Sphere,所以本文已经过时,不日将推出新的版本 项目中遇到了分库分表的问题,找到了shrding-jdbc,于是就搞了一个springboot+sharding-jd...
摘要:项目介绍风格的一套系统,前端采用作为前端框架,后端采用作为服务框架,采用自封装的对所有请求进行参数校验,以保证接口安全性。 skyeye 项目介绍 win10风格的一套系统,前端采用layui作为前端框架,后端采用SpringBoot作为服务框架,采用自封装的xml对所有请求进行参数校验,以保证接口安全性。 项目地址:https://gitee.com/doc_wei01_a...该项...
摘要:时间年月日星期四说明本文部分内容均来自慕课网。那么里面的数据就可以分为各种各样的索引,比如汽车索引图书索引家具索引等等。图书索引又可以细分为各种类型,比如科普类小说类技术类等等。具体到每一本书籍,就是文档,就是整个图书里面最小的存储单位。 时间:2017年09月14日星期四说明:本文部分内容均来自慕课网。@慕课网:http://www.imooc.com教学源码:无学习源码:https...
阅读 1889·2023-04-25 23:43
阅读 1009·2021-11-24 09:39
阅读 790·2021-11-22 15:25
阅读 1790·2021-11-22 12:08
阅读 1174·2021-11-18 10:07
阅读 2144·2021-09-23 11:22
阅读 3439·2021-09-22 15:23
阅读 2707·2021-09-13 10:32