栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Spring

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Spring

录播的课是基础的课(菜鸟预习):JavaSE基础 HTML css Javascript maven Git Linux基础
直播的课:JavaEE高级框架
十天的时间:spring—》SpringMVC—》SpringBoot—》一个SpringBoot的项目;

《spring》 第一课:spring,IOC入门与详解

1.spring可以做什么?—控制反转Ioc/di 面向切面编程AOP 事务的管理
springframe就像是一个托儿所一样,可以来帮我们来管理我们的孩子,我不需要在管理孩子了,将控制权交给了托儿所;
IOC是一套思想,DI是一套解决方案,DI是注入;
spring可以理解为一个容器,是一个大篮子,里面可以存放很多对象,这个容器有控制反转和面向切面编程的功能;
AOP是一个开闭原则的实现,比如动态代理;

spring可以用来继承各种各样的框架,比如SSH、SSM。现在是主要用SpringBoot来集成各种各样的框架了,可以理解为SpringBoot是spring的升级版;

2.spring data jpa和mybatis的区别
小项目:spring data jpa
大项目:mybatis

可以学习SSH;

3.springframework的HelloWorld程序
【问题】
springframework的程序和普通的javase程序有什么区别呢?
springframework的程序相比于JavaSE的程序有哪些不用的地方,JavaSE可以做哪些开发出哪些应用程序,可以用于哪些用途,有什么缺陷和不足,不可以开发哪些应用程序,而这些不足有哪些是可以通过springframework来改进的,springframework可以开发哪些JavaSE不能开发的应用程序?
下载spring的jar包;

开发工具
spring tool suite-STS:用STS来创建spring的项目,比eclipse多了一些spring的功能;

springframework的HelloWorld程序:来体验一下spring的程序是什么样的?
new一个普通的spring项目,项目的目录结构下只有一个src,这和普通的java目录是一样的;
在src目录下新建一个配置文件:applicatinContext.xml(这是和JavaSE不一样的)
在src下新建包和类:和JavaSE一样,在src下面new一个class ,同时有get和set方法;
测试:new一个TestClass
new一个文件夹libs,然后呢将四个spring核心的jar包放到这个文件夹下,然后将它们build到path中,就可以使用spring的jar包了;

使用spring:在testclass中,new一个对象ClassPathXMLApplicationContext,然后就可以使用spring的jar来管理bean对象了!!这就是spring的第一个功能,用于管理bean对象;
管理对象是指:可以new对象,可以为对象设置属性,可以获取对象的属性值,自动了完成了对象的创建、使用和销毁;
重点是:applicationContext.xml 的配置文件和如何使用spring的对象管理bean;

对比之前的方式:
Person person = new Person();
person.set();
person.get();

小工具
spring Commons里面的工具类
ToStringBuilder.reflectionToString(person)—相当于是重写toString方法;

依赖注入DI
需要一个无参和有参的构造方法;
可以通过配置文件来替换set和get方法,就可以完成对象属性的设置,也就是注入;
constructor-arg name=“name” value=“jly” ----使用name-value
constructor-arg name=“food” ref=“food” —使用name–ref

分析applicationContext.xml文件配置的组成(????)
beans标签,是最小的IOC配置,里面有一个想xmlns=xml namespace,namespace有点像是一个接口;
xmlns类似一个id,有点像包的权限路径,xml的namespace,是一个id,类似于package;
xmlns:xsi是xmlns的一个子目录二级标签,xsi是用于校验规范用的,类似于一个规范;
xsi:schemaLocation:是具体用到schema的资源;
bean:产生的对象
applicationContext.xml的分层:可以将不同层的bean放到不同的xml文件中;
当xml文件多的时候,可以使用import来互相引用不同的xml文件;

【技巧】看spring异常的小技巧:看所有报错的第一行,然后看第一行的最后信息,一般就可以找到错误;
【作业】引入jar,做一个spring的helloworld;
1.new一个普通的Java项目,里面就一个src目录文件;
2.在src目录下new一个applicationContext.xml文件,xml文件里面的内容;
3.new一个lib,将spring依赖的核心jarbuild 到path中;
4new一个Person类,是一个bean类;
5.测试类,TestSpring类里面new一个对象就可以进去到容器中,使用spring容器来管理对象了;

第二课:maven简单构建AOP

本节课内容:把第一节课剩下的IOC内容讲完;
DI注入(属性注入、构造器注入、进入注入)、一些重要的IOC属性(懒加载)、注解注入、面向前面编程(概念,在Springboot中编码体验面向切面编程)、动态代理、一些经典的面试题目;

0.回顾:getBean和一个工具StringToBuilder的使用
1.使用maven来创建一个spring项目
new maven project / new maven moudel
groupID:组名,类似于包名
artifactID:项目名
在pom文件中倒入spring需要的依赖dependency:spring context、spring core
在src/main/resouces目录下new一个applicationContext.xml文件,普通Java项目是src下,和maven项目不一样;
new一个Person类,是一个bean类;
在src/main/java下new一个TestGetBean类,用于测试;

2.给bean起别名
一个bean只能有一个ID,而可以有多个name
为一个bean起别名,alias

3.property标签属性注入方式(比较常用)
注入bean的方式有两种,一种使用构造方法注入,另一个是使用属性注入。属性注入是使用了bean的set和get方法来进行注入的;
property的标签 name–value

4.通过p-namespace和c-namespace来注入
先添加一个xmlnsp:添加一个namespace,一个是p一个是c;

5.属性property的注入
在Person类中加入一个Property 类型的属性;
注入:property name-value
作用:读配置文件和解耦

6.耦合
强耦合:classA-----引用----》classB
松耦合:classA----引用xml-----》classB,当classB变化时,更新一个classB就可以了,不用改classA;
松耦合的案例–MVC三层架构:
M:业务逻辑 service和dao
V:视图层 JSP
C:控制层 servlet
先写接口interface----》然后再implement这个interface,一旦业务有变化,不用改变接口,只用改变实现类就可以了;

7.注入集合类型
List、Set、Map和数组;
List<>: property name–array—value
Set<>:property name —array–value
Map<>:property name —map —entry–key/value 或 property name --props–prop

8.作用域—相当于生命周期
getBean获得的对象是单例的,spring获得的对象默认是单例的
singleton scope:单例模式
prototype scope:原型作用域,就相当于是new出来的一个对象;
websocket scope:基于连接的单例模式
request scope:基于请求的单例模式
session scope:单例模式
application scope:单例模式
单例的意思是:程序在运行的时候只有一个对象,所有的变量person1 person2 person3都指向同一个对象,他们共享这个变量;
Spring对象的产生有两种方式:一种是new出来的prototype ,一种是单利的singleton,单例是指一个生命周期内,只有一个对象;

【问题】什么情况下使用什么类型的生命周期?spring在MVC三层架构中的作用
架构演变:servlet(重写service方法)和jsp----》ssh和SSM–》springboot分布式—》
Model层:模型层,包括了service业务层和处理curd的dao层;
View层:给用户response的前端页面;
Controller层:处理不同的URL,然后转到service层;
SSM:spring+springMVC+mybatis
spring的作用:一些controller层、service层和dao层的对象都是单例的,pojo的对象不是单例的。所有归spring管理的类都是单例的singleton,pojo不是单例的,是不归spring管理的;
spring的作用:单例初始化一些controller层和service层的对象,提高了性能,但是也是有一些并发问题.。
容器:用户的信息是存放在线程中的,一个用户容器分配一个线程,当多个线程访问单例类的成员变量时,存在线程读写安全问题。所以,在单例的类下,不可以存在成员变量;如果加锁的话,就会影响性能;
spring在SSM的作用:相当于new对象,而且这些对象都是单例的,同时完成这些对象的注入;pojo是由springnew出来的,但是它们的生命周期是不由spring管理的;
**【问题】**controller层的对象是单例的,每个用户都会使用同一个单例对象;
jdbc的Connection是单例的;

9.懒加载lazy-init
bean对象的生命周期:getBean方法被调用的时候,spring容器就实例化这个对象了;

【作业】创建三个类A、B、C;A类引用B类,B类引用C类,C类引用A类(循环引用三个对象),使用spring初始处理;

10.动态工厂方式的注入(????)
【作用】:在配置文件中动态的选择spring容器要生成的对象;
【方式】:在bean中定义一个工厂,工厂也是一个bean,和普通的bean定义一样,有id有class;在定义另一个bean,有id, factory-bean factory-method 还要一个constructor,通过constructor传递参数,就可以根据参数来创建对象了;

bean的class指定了要创建的类,但是可以通过工厂的方式来决定spring要创建的对象;
什么事Java的工厂:工厂就是传过来的对象来获取不同的对象;
new 一个Car的interface,有两个实现类,Car1 和 Car2;
实现一个CarFactor类,有一个通过name来new对象的方法;
通过new一个CarFactor类然后调用方法来new Car的对象(方法有问题,不能解耦合);
解决:通过配置bean来获取Car对象;
bean id= factory class= CarFactory
bear id = car factory=factory

11.静态工厂
getCar是一个static方法,而动态方法是没有static关键字的;
static方法通过类来之间调用;
动态工厂是每次都是new出来的;
动态工厂和静态工厂都是设计模式的东西;

【作业】三个类循环引用和null的注入

第三课:Spring的循环依赖,代理方式

今天课程的任务:depends-on、lazy-init、 单例问题 、循环依赖的bean 、null的注入、 annotation注解注入、 代理模式 过度到springboot;

1.循环依赖
【两种方式】通过constructor方式可以成功,通过property方式会失败;
【原因】property方式在new对象的时候,会将对象中的引用对象也给new出来,所以就会出现循环引用的死循环;而单例模式的情况下,会直接的new出这个对象;
【spring容器】spring容器里面有一个注册表:里面存放了key-value的键值对;
【单例】单例方式相当于自己new对象:先new A 在new B 最后new C;这个时候三个对象就是存在的了,然后再通过set方法将对象引用的对象注入进去,new这种方式有一个问题,对象不会被销毁,可能造成内存溢出,但是spring容器处理了这个问题;
单例对象的引用对象也是单例的,这是spring容器内部设置的;

2.属性:depends-on提前初始化
【弱引用】循环依赖是强引用,直接在一个class中引用另一个class。弱引用是不直接引用一个对象而是引用这个对象的静态成员属性;
【例子】classA中引用了classB的static属性,classA在使用这个属性的时候,classB必须引进new好了;不然会报出空指针异常;
【解决】bean是至上而下new对象的,可以将beanB放在beanA的前面手动控制,也可以通过depends-on属性来控制创建对象的顺序;在beanA标签中,depends-on beanB,这样的话beanA会在beanB之后创建;

3.属性lazy-init 懒加载
懒加载是:当需要用到程序的时候才加载这个对象,不用的时候就不加载,当应用程序很大的时候,可以通过懒加载提高程序的启动速度;

4.空值注入
空值和null的区别:一个字符串里面为空的时候就是一个空值,在C语言中表示的是 ‘/0’ ,而null是指的是一个引用地址为空,不指向任何一个地址;
【null引入】 null标签
【空值引入】

5.自动注入,自动装配
【问题】当在classA中引用了classB时,可以通过自动引用标签autowire来完成自动装配;
【autowire】在beanA中加入这个标签,通过byName的方式来完成自动注入;注意beanB的id要匹配;
【全局的自动装配】在xml文件中加入 default-autowire=“byType”,这是通过类型的方式来引用,当出现循环引用的时候,可以加入全局的自动装配,就不需要在每个bean中写autowire的标签了;
【问题】上述的方式还是需要写bean,还是需要写property和constructor等一些配置文件,对这些bean的省略可以通过注解的方式来省略;

6.注解
【导包】在xml文件中就是加入namespace spring-context的namespace,namespace就是约束
【功能】可以不用写bean标签了;可以不用写property来set值,可以进行面向切面的编程;
【搭建项目结构】 controller层、service层、dao层的三层架构、entity层(Person类,一个entity对象对应数据库的一个表,可以是虚拟的表)
【controller层】负责逻辑跳转,在web下,由controller接收前端带来的URL;然后调用service层的的方法;
【service层】处理具体的业务逻辑,可以有校验功能;
【注解】
@Component(“id”):代表注册bean,相对于bean id = “”,默认是按照类型来创建对象,由spring来管理这个对象的生命周期;
@Autowire:自动装配,相对于autowire标签,在classA中引入classB的时候,通过这个注解来自动的引入对象;

【xml配置】
context:component-scan base-package=“class-path”:扫描具体包下的带有@component的所有class,然后将这些class交个spring容器管理;

【启动类】
需要一个启动类,也就是MVC的main方法,入口方法;
通过getBean(“id”)方法来new一个controller对象,然后调用controller对象的方法;

【回顾】
首先是:applicationContext在进行包扫描,将所有的@component的类交给spring容器管理,相对于是bean标签;
然后是:@Autowire标签是通过类型的方式来在一个class中自动注入另一个class,默认是byType的方式;
最后:通过main方法来启动这个程序;
注意:如果注入到class的是一个interface,spring容器实例化的对象就是这个接口的实现类,所以不需要在interface上面加入@component,而在实现类上面加入@component;
当接口的实现类有多个时,在@component中加入id,然后再使用@Qualifier 配合@Autowire一起使用,用于查询指定id的@component;

【开发现状】
之前的时候写一个接口,然后有多个接口的实现类;根据不同的方案来使用不同的接口实现类;比如查询数据库的时候,有MySQL的实现和Oracle的实现;所以有两个不同的实现类;
这是面向接口的编程;

7.User类
一个线程创建连接一个线程关闭连接;这个类是Connection类,会存在线程安全的问题,是ThreadLocal来控制线程,达到线程安全问题的,所以Connection这个类可以是单例的;
【区别】controller层 service层和dao层的对象都是没有成员属性的,所以都是单例的且不存在线程安全的问题;
【线程安全】user类是和数据库表一一对应的,ORM映射,有成员属性,每个成员属性对应数据表中的一个字段,所以也是有线程安全问题的;当entity类是单例的时候,多个线程访问controller的时候,多个线程对应一个controller,对应一个MySQL,对应多个User类对象;
【过程】多个用户请求访问—(一次请求一个线程)--------》对应多个线程—》一个controller(单例)—》对应一个MySQL(单例的Connection)-------》对应多个User类(一个线程一个User类)
【初始化User】根据过程来看,所以User类不能是单例的;
@Component
@Scope(“prototype”)

【注入属性值】在没有连接数据库的时候,通过@value给User属性注入值;
在User类中:
@Value(“value”)
private String loginName;
简单的属性用@Value
复杂的属性用@Autowire
为了区分各个@Component之间的区别,为三个层设定了三个特殊的注解;下面就是一个三层架构的MVC模型;
controller层:@Controller
service层:@Service
dao层:@Repository

8.作业
【作业】使用maven构建三层架构MVC的spring项目;
这里的三层架构指的是:控制层、服务层和模型层,没有设计到前端的东西,没有设计URL和前端请求;
spring项目的运行过程:
1.controller层:引用service层的class
2.service层:处理业务逻辑,引用dao层class
3.dao层处理数据库的连接crud
4.写一个entity类
5.在xml文件中设置包扫描,将全部的对象交给spring容器管理;
6.写一个main方法来getBean controller层的对象模拟整个项目的运行过程;

9.动态代理(????)
spring的两大核心:控制反转依赖注入 和 面向切面编程;上面的学习就学完了控制反转和依赖注入了;
控制反转:就是将class对象的创建交个spring容器来管理
创建对象的演变过程:xml文件写bean—》通过注解@Component—》注解@Controller、@Service、@Repository
依赖注入的演变过程:xml文件写bean–property—》xml文件写autowire—》注解写@Value和@AutoWire;
学会依赖注入就可以去做MVC的三层架构的spring项目了;

【spring的底层】:get set proxy CGlib
通过JDK和proxy和CGLib把的方法监控起来,在执行这个方法之前或者完成之后做一些事情,可以监控代码执行的状态和顺序,这就是动态代理;

【静态代理】
有一个对象Girl,有一些方法eat()和bath(),eat()是public的可以看,而bath()是private的私有的不可以看;
有另一个class Boy,想要访问Girl的private方法,怎么办呢?通过代理来实现;
有一个代理:它可以看到Girl的所有方法,对Girl的所有方法进行包装修饰,但是方法的访问修饰不变,但是可以改变方法的返回值,可以在方法执行的前后进行修改;
实现一个代理之后,Boy就可以通过代理来访问Girl了;
这就是代理类的作用,将一个原始类进行了包装盒修饰;
Girl《-------代理类《---------Boy

【关键:如何实现一个静态代理】
继承一个接口:Human,规定了一些方法,比如eat() bath()
Girl也是实现Human这个接口,然后实现了Human的方法,eat() bath()
代理类ProxyGirl:引入了一个依赖Human,然后去修饰这些方法,eat() bath();代理对象还有一个构造方法,对Human进行赋值,但是呢Human是一个接口不可能实例化对象,所以这里就使用了多态的功能;当传入的参数是Girl时,这个时候代理的就是Girl;
【缺点】当方法是private的时候,Boy还是不可以通过代理访问来这些方法的;
静态代理是一个写一个类,一个代理类代理一个对象;
【动态代理】
动态代理是面向于JDK接口的代理,和Girl一样实现了同一个接口;对接口的方法进行增强;用的是Proxy这个类;
但Girl没有实现一个接口的时候,就使用GCLib来继承这个;使用一个类来实现MethodInterceptor来实现动态代理;new一个增强器enhancer来增强这个方法;

【ASM–?????】马老师的课 ,ASM只上的就是proxy CGlib,动态代理的实现方式;

【回顾】
depends-on和lazy-init控制spring的注册表来完成对象的创建顺序;
循环引用的问题
空值和null
自动装配autowire,byType和byName
静态代理和动态代理
作业:使用maven构建一个MVC的项目使用spring注解;

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/362190.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号