https://www.youtube.com/watch?v=8e1v8QlHNyQ&t=451s
没有标准答案,面试时候,你不要官方回答,你要理解了。你官方回答,里面会有特殊的词汇。
面试官也听不懂,这问题就接踵而来了。
比如说什么是对象,万物皆对象。十年前这么说可以,现在这么说,你完蛋了。
什么是万物皆对象。
面试时候回答问题,一定要有总结性,要有自己的理解。
框架,就是框和架,框就是有一定的约束性,架就是有一定的支撑性。
什么是框架,就是具有约束性地去支撑我们实现某些功能的半成品的项目。
没啥意思。
SSM = spring + springmvc + mybatis
structs1
stucts2
hibernate
spring
springmvc
mybatis
这些框架都是开源。
开源不等于免费。
免费是不掏钱。开源就是既免费,又可以自由传播。
这六个框架当中,听说过apache吗,tomcat就是apache的。
structs1、structs2、mybatis都是apache开发的。
hibernate是JBOSS开发的。
spring和springmvc,是interface21开发的。
杨博超毕业去面试,就成功了,第一次面试,面试官给了试题,都不会,就会一个html。
杨博超大学时候学的是asp、.net、c#。
c、c++、c#。
面试的时候,笔试题都不会。
上大学听说不用上课,就再也不用上课了。
手机查了两道题,就做了三道题。
面试的是总经理,公司是上海的,在郑州出差,面试。
面试的时候问公司里面是不是用c#,总经理说是,进去之后发现用的是basic。
Spring是一个开源框架
杨博超电脑是win10家庭版的,获取最高权限,有些文件夹权限还获取不了,专业版还是1000块钱左右。
myeclipse和eclipse不是一家公司开发的,是需要收费的。
unix操作系统是最早的操作系统,有声电影就是贝尔实验室开发的。1960到1970年左右,买一个unix操作系统要五万美元,不能随便找个机器装上,要小型机或高端服务器才能够装上。当时的小型机就能够8核,好几万美元。
所以说,开源是一个趋势。
- Spring为简化企业级开发而生,使用Spring,JavaBean就可以实现很多以前要靠EJB才能实现的功能。同样的功能,在EJB中要通过繁琐的配置和复杂的代码才能够实现,而在Spring中却非常的优雅和简洁。
EJB不是spring的前身,直接从jsp+servlet+jdbc切换到spring,不会很适应。
以后你什么框架都不用,但是spring肯定会用。
- Spring是一个IOC(DI)和AOP容器框架。
spring的两大核心,一个叫做IOC,一个叫做AOP。
当然了,说几种情况,面试给你笔试题,问你spring的核心,只有一个填空,填写什么呢?
这个时候,你填写IOC,两个填空,就填写IOC和AOP。
- Spring的优良特性
① 非侵入式:基于Spring开发的应用中的对象可以不依赖于Spring的API
② 依赖注入:DI——Dependency Injection,反转控制(IOC)最经典的实现。
③ 面向切面编程:Aspect Oriented Programming——AOP
④ 容器:Spring是一个容器,因为它包含并且管理应用对象的生命周期
⑤ 组件化:Spring实现了使用简单的组件配置组合成一个复杂的应用。在 Spring 中可以使用XML和Java注解组合这些对象。
⑥ 一站式:在IOC和AOP的基础上可以整合各种企业应用的开源框架和优秀的第三方类库(实际上Spring 自身也提供了表述层的SpringMVC和持久层的Spring JDBC)。
大家有没有听过轻量级和重量级。轻量级就是非侵入性。
jquery就是对javascript的轻量级封装。
最重要的是,并不需要让我们过渡依赖某些东西。
使用了轻量级技术之后,对你原来的技术不造成影响。你引入了jquery,还可以使用js,可以使用jquery的选择器,也可以使用document.getElementById。加入spring之后,spring可以管理对象,但是我就是想要自己new对象,都可以,这就是轻量级的意思。
IOC也可以叫做DI,DI叫做依赖注入,IOC叫做控制反转,反转控制。
IOC可以理解成为一种思想,DI可以理解成为一种实现。
语言的魅力就是他明知道你骗他的,他还相信的。
AOP是面向切面编程,OOP是面向对象编程。
因为OOP存在某些缺陷,有了AOP面向切面编程,对OOP进行补充。
AOP是为了对OOP进行补充的。
spring是一个容器,管理应用对象的生命周期。
tomcat是一个容器,管理servlet的生命周期。
为什么学习spring。
没有学习spring对象之前,我们是new 构造方法创建对象。
new 构造方法一般执行一次,内存空间开辟。
如果整个复杂项目功能中,创建了1000个对象,要开辟1000个空间。
保证在整个过程中,一直用这些对象吗?不会的。
咱们有时候也不需要创建这么多的对象。
咱们讲过单例:不需要创建那么多的对象,只需要实现一个单例,就可以。
但是这个单例,我们还要自己写。
当我们使用了spring之后,咱们就可以将对象交给spring管理。
等于将对象放在spring容器中。
web容器能够管理servlet的声明周期。
spring容器就是能够管理应用对象的声明周期。
spring实现了,使用简单的组件,配置组合成为简单的应用。
每一个项目对我们来说,由各个类,由类产生对象,由对象产生方法,实现功能。
将所有用到的类,全部交给spring管理,然后把这些类叫做组件。
spring当中的组件就是spring管理的对象。
原来我们需要什么对象,就创建什么对象。现在不是的。现在spring把我们需要用到的组件拼装起来。
spring能够降低程序的耦合,让类与类之间的关系,不是那么强大了。
组件化,可以理解为降低耦合。
在IOC和AOP的基础上可以整合各种企业应用的开源框架和优秀的第三方类库(实际上Spring 自身也提供了表述层的SpringMVC和持久层的Spring JDBC)。
spring这个家族真实牛逼。
从下往上看,最基本的叫做core container
最下面,最基本的就是beans,管理beans的,就是ioc。
数据访问层
Websocket
Servlet
Web
Portlet
这就是以后要讲的springmvc框架,特别方便简单,大家原来用servlet的时候,获取客户端数据是request.getParameter。springmvc当中只需要在处理请求的方法上,加上参数就可以自动获取。还比如说,大家原来都用过ajax,都学过json,我通过ajax获取java中的对象的时候,能直接获取吗?不能,需要先转换成为json,然后响应。原来你转换json,需要用到一个工具类,这些工具类是特别多的。比如说jackson。也是处理json,还有阿里巴巴开发的fastjson,这个东西,杨博超用的比较多,非常方便,json.toJson就好用。
在springmvc当中转换json的过程,根本就不需要你写。自动转换为json。
这个图,大家可以简单理解一下。
把spring的运行原理要记到脑子当中。
这个东西是eclipse的产品。
不要钱的。
这个东西,跟eclipse有什么区别。
STS是专门为spring来设计的。
给spring提供了非常多的方便。
访问网站:https://www.oracle.com/java/technologies/javase/javase-jdk8-downloads.html
参考这个文章:https://blog.csdn.net/louisgod/article/details/76092950
咱们选择java视图。
不需要的视图,都关闭掉。java项目是需要用到一个控制台。
- 加入JAR包
① Spring自身JAR包:spring-framework-4.0.0.RELEASE\libs目录下
spring-beans-4.0.0.RELEASE.jar ---------------这就是IOC的功能
spring-context-4.0.0.RELE2ASE.jar------------上下文
spring-core-4.0.0.RELEASE.jar--------------核心jar包
spring-expression-4.0.0.RELEASE.jar-----------表达式
② commons-logging-1.1.1.jar
web项目jar包可以放在lib当中,java项目,咱们放在哪里呢?
我们可以新建一个文件夹。
source folder是放源文件的。
folder是放普通文件的。
有时候发现,写某些功能,大部分都导入日志jar包。
但是导入日志jar包,根本没有用,确实会输出一些日志。
为什么?
这个jar包不需要管。
框架当中默认使用某些日志功能的。
比如mybatis,apache开发的。apache当中有一个log4j的jar包。
apache还开发了一个dom4j,这里的4就是four,就是for,j就是java。
j2ee当中的2就是to。
i18n就是国际化。
为什么呢?
mysql当中不给字段赋值,默认就是null,从数据库查出来就是null。
如果你的类的字段是int,null是不能给int赋值的。
这是第一个问题。
实体类中的属性,可以赋值,也可以不赋值。
不赋值,int就是默认值是0。
double是0.0。
所有的引用类型都是null。
如果类属性是int,我主动设置为0,或者默认是0,业务意义是不一样的。
所以以后不要再用基本数据类型了。直接用包装类。
int就是integer
char就是character
double就是double
boolean就是boolean
然后写一个单元测试。
Junit最主要的用处,就是不需要写那么多的main方法,只要加一个@test注解,就可以执行方法。
正儿八经没有学习到junit的精髓。
现在我们使用junit就是为了每个方法都可以执行。
这个时候,可以为属性赋值。
这就是原来的一种方式。
需要把对象,交给spring管理
需要在配置文件当中进行对象的配置。
我们接触的最早的配置文件,就是web.xml,这被称之为入口配置文件。
只有web.xml被加载成功了,项目才能够正常执行。
web.xml配置servlet的时候,少写了一个斜线,多写了一对标签,这样启动都启动不起来。
web.xml是在web项目当中占据了非常大的作用。
框架当中也是的。
咱们刚才说的六个框架,都是xml作为配置文件的。
咱们需要创建一个配置文件,把对象配置到配置文件当中,才可以说,对象交给了spring管理。
xml非常非常厉害,是叫做可扩展标记语言。
什么意思。
可以看到web.xml和spring的xml根本不一样。
会发现xml扩展性特别强大。
所有的标签都是需要你自己定义的。
什么叫做可扩展,这里面没有任何的提示。
所有的标签都是自己定义的。
这是spring默认的配置文件的名字。
这个名字是spring配置文件默认的名字。
等到大家做SSM整合的时候,需要把加载spring配置文件的过程,放在web.xml当中。自动加载spring的配置文件,需要加载这个名字的配置文件applicationContext.xml。
beans标签当中写的玩意,叫做命名空间。
命名空间是,规定你的xml当中,能够写什么标签,不能写什么标签。
这个bean不是javabean,这个bean就是对象。
bean代表的是对象,对象由类而来,类的实例化就是对象,我们要规定这个对象,由哪个类,实例化的。
我们的bean标签里面要有class属性,class属性的值,是一个全类名。
到这里,下课了。
第一步,初始化容器。
spring管理的bean,就是放在spring的容器中。
我们要获取spring的容器对象ApplicationContext。
这是一个接口,接口不能直接实例化,我们需要通过接口的实现类来进行实例化。
接口的实现类是ClassPathXmlApplicationContext,这个实现类有一个重载方法,里面是放置configLocation,就是配置文件的路径,我们的配置文件是在conf下面的。
conf下面的东西,最终是会加载到类路径下面的。
spring当中管理多个bean,我们怎么通过ApplicationContext获得对象呢?
我们可以给bean加上一个id属性。
id属性是唯一标识,只要保证不重复,就可以了。
获取bean对象的时候,通过id获取。
在这个IDE当中,通过ctrl+1获取返回值。
或者使用快捷键alt+shift+l
返回值是一个Object呢?
只有当代码执行的时候,执行过程中,执行到这一步了,才知道bean是一个Person类型。
在代码编写的时候,直接写的是Object。
我们可以强制类型转换一下。
Object是所有类的直接父类或者间接父类。
咱们都学过向下转型和向上转型。
向上转型:
通过子类的构造方法,创建父类的对象。
通过实现类的构造方法,创建接口的对象。
向下转型:
将上转型对象/父类对象,强制转换为子类对象。
这样我们就通过容器的getBean方法,从spring中获取了对象。
现在看到了Spring创建对象的过程。
通过配置文件当中的子标签,给属性进行赋值。
再执行一下:
这就是spring管理bean的写法和过程。
- 在Spring Tool Suite工具中通过如下步骤创建Spring的配置文件
① File->New->Spring Bean Configuration File
② 为文件取名字 例如:applicationContext.xml
这个配置文件的名字是可以改变的。
singleton就是单例。
prototype就是原型,就是多例。你每次new构造方法,就要分配空间,要创建对象。
在java当中对象模式,是多例的。
什么叫做依赖,对象和对象,对象和属性的关系。
我要创建一个对象。
这个对象依赖另外一个对象。
咱们有了spring之后,对象不需要咱们维护,对象的关系,也不需要咱们维护。
什么叫注入,注入就是赋值。
比如说car对象依赖发动机对象,方向盘对象。
普通的完成过程,在car的内部,new一个方向盘对象,发动机对象,这就是普通的做法。
注入就是,依赖谁,就注入谁,就是为谁赋值。
刚才的例子,依赖两个属性,所以就给属性进行赋值。
IOC就是一种思想,DI就是具体的实现方式。
getBean有多个重载的方法。
同名不同参数的方法,就是重载方法。
看第一个方法,就跟反射相关。
什么时候学过Class对象。就是反射的时候。
Class.forname
对象.getClass
类名.class
我们可以通过类型对应的class对象,也可以获取对象。
如果我们用这种写法,跟id没有什么关系。
我们在配置文件当中,将对象的id删除,也是可以正常获取到的。
id可以不设置,通过类型Class对象获取bean的过程中,可以不设置。
如图所示,我们配置了Person的两个对象。
我们在getBean的时候,怎么获取?
如果是这样,就报错了:
把所有遇到的错误,复制下来记录到一个文档当中。
十月 01, 2021 3:37:41 下午 org.springframework.context.support.ClassPathXmlApplicationContext prepareRefresh
信息: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@4783da3f: startup date [Fri Oct 01 15:37:41 CST 2021]; root of context hierarchy
十月 01, 2021 3:37:41 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
信息: Loading XML bean definitions from class path resource [applicationContext.xml]
Exception in thread "main" org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [com.atguigu.spring.mod.Person] is defined: expected single matching bean but found 2: PersonOne,PersonTwo
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:312)
at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:985)
at com.atguigu.spring.mod.TestBySpring.main(TestBySpring.java:10)
如果你在配置文件当中,配置了两个一个类的对象,这个时候,如果你getbean的时候,通过class获取bean,容易出现下面的错误。
NoUniqueBeanDefinitionException
有个人,在航空公司做培训。
把工作当中遇到的所有问题,记录到本子上。
换工作的时候,换到另外的航空公司,这个公司领导不让走。
要么把本子留下来,要么人留下来。
公司开的条件,你只要不把本子给别的公司用,给你涨工资,你想去哪里去哪里。
使用这个方法获取对象的时候,要求spring管理的此类型的对象,只能够有一个。
getBean(String arg0,Class arg1)
以后推荐大家使用这个方法,来获取bean。
咱们将对象以bean标签的方式,写到了配置文件当中。
我们初始化容器的时候,就会加载配置文件,读取配置。
怎么根据标签,就创建了对象了呢?
反射当中有一种获取class的方法,叫做class.forName(全限定名),通过获取的class对象.newInstance方法,就可以创建对象。
所以,我们推测spring是通过反射的newInstance方法来创建对象的。
new Instance方法创建对象的时候,有一个条件,类必须要有无参构造器。
我们现在的Person对象当中有构造方法吗?
这里有一个缺省的,默认的构造方法,是无参的。
我们创建一个有参的构造方法:
这个时候,就有了。
然后我们再测试一下通过Spring来获取对象。
这个时候,就报错了:
十月 01, 2021 3:48:59 下午 org.springframework.context.support.ClassPathXmlApplicationContext prepareRefresh
信息: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@4783da3f: startup date [Fri Oct 01 15:48:59 CST 2021]; root of context hierarchy
十月 01, 2021 3:48:59 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
信息: Loading XML bean definitions from class path resource [applicationContext.xml]
Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'PersonOne' defined in class path resource [applicationContext.xml]: Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [com.atguigu.spring.mod.Person]: No default constructor found; nested exception is java.lang.NoSuchMethodException: com.atguigu.spring.mod.Person.()
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:1076)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1021)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:504)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:475)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:304)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:228)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:300)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:195)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:700)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:760)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:482)
at org.springframework.context.support.ClassPathXmlApplicationContext.(ClassPathXmlApplicationContext.java:139)
at org.springframework.context.support.ClassPathXmlApplicationContext.(ClassPathXmlApplicationContext.java:83)
at com.atguigu.spring.mod.TestBySpring.main(TestBySpring.java:9)
Caused by: org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [com.atguigu.spring.mod.Person]: No default constructor found; nested exception is java.lang.NoSuchMethodException: com.atguigu.spring.mod.Person.()
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:85)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:1069)
... 13 more
Caused by: java.lang.NoSuchMethodException: com.atguigu.spring.mod.Person.()
at java.lang.Class.getConstructor0(Unknown Source)
at java.lang.Class.getDeclaredConstructor(Unknown Source)
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:80)
... 14 more
这个错误,叫做:NoSuchMethodException
。
学习反射的时候,经常见到这个错误。反射当中什么情况下,会遇到这个错误。
getDeclardMethod的时候,会遇到这个错误。
这里这个错误是什么意思呢?
如果以后在spring当中遇到错误,别的不用看,就看最后一个,就是最根本的问题。
我们给类当中写了一个有参构造方法,这样就将原来的无参构造方法,覆盖掉了。
这说明了,spring就是根据反射的原来,来创建对象的,是需要用到newInstance方法的。
newInstance方法是要求类当中必须要有无参构造器的。
补充上去无参构造器之后,再测试,就正常了。
我们通过ctrl+shift+t,为了open type。
这是一个接口。
极端的抽象类,就是一个接口。
抽象类当中可以存在抽象方法。
接口当中全部都是抽象方法。
不看这个BeanFactory.class的源码。
我们看一下ApplicationContext的源码。
然后在这里按照ctrl+t,就出来这样的东西:
可以看到整个的继承实现关系。
可以看到最顶层的接口,叫做FactoryBean。
我擦,不是BeanFactory吗?
再来一次。
打开是这样的:
这里就是BeanFactory了。
刚才是咋回事?
不知道。
这就列出来了所有的实现继承关系。
BeanFactory下面有一个子接口,叫做ApplicationContext。
ApplicationContext下面有一个ConfigurableApplicationContext。
咱们使用的是这个接口的实现类,就是ClasspathXmlApplicationContext。
还有一个实现类,叫做FileSystemXmlApplicationContext。
两个的区别是:ClasspathXmlApplicationContext,这个配置文件是在项目当中的,是在类路径下的。
如果你有一个文件服务器是专门用来放文件的,如果你要加载文件服务器上面的配置文件,就要用到FileSystemXmlApplicationContext。
这里提示我们从来没有关闭过。
关闭一般都是close方法。
但是我们发现,根本就没有close方法。
ApplicationContext是一个接口,这个接口是没有一个关闭的方法的。
我们可以去它的子接口当中找一找,到底有没有关闭的方法。
接口越往下继承,功能约全的。
这个时候,我们就发现了ac是有close方法的:
我们也可以直接这样用:
这个webApplicationContext,这个是我们使用springmvc的时候,才会使用到的。
内容还是非常多的。属性,其实就是一个变量。
属性要有类型。
java当中的类型,挺多的。基本数据类型,引用数据类型。
引用数据类型当中,包含一些基本的包装类,还有集合,数组。
给bean的属性赋值,早上的时候,就是依赖注入的过程。
IOC叫做把程序员对一个对象的管理权,反转给程序本身。
依赖注入,把具有依赖关系的属性进行赋值。注入就是赋值。
依赖注入的方式有好多种,咱们就讲解两种。
第一种叫做set注入,第二种叫做构造方法注入。
设置一些属性。
设置set和get方法,然后给一个toString方法。
创建配置文件。
这也是咱们起名字的时候,经常会用到的一个名字。
对象的属性都是私有的。
访问修饰符:private、默认的、受保护的、公共的。
设置为private,能够直接访问吗?不能够的。
property标签是通过什么方式,给属性赋值的呢?
应该是set方法。
点进去,看到下面:
我们在property标签当中设置的id,主要对应的是对象的set方法当中,setId的名字。不是对应,对象的属性名字。
这种情况,我们测试,也是可以成功赋值的:
所以,严格上来说,property当中的id,并不是对应对象的属性名字,而是对象的set方法。
以后的配置基本上都是用这一种的。
在对象当中写一个无参和有参的构造方法:
我们可以通过有参构造器,可以给属性赋值。
这个就是通过局部变量为全局变量赋值。
spring当中为属性注入的时候,也可以通过构造方法注入。
成功赋值了,为什么呢?
在对象当中有一个四个参数的构造方法。在constructor-arg,会自动匹配到实体类当中相对应的构造方法。
如果我们修改有参构造器:
配置文件直接报错,因为在student当中,只有一个无参构造和三个参数的构造方法。
给student对象添加一个score属性:
然后我们多写一个有参构造器:
这样对象当中都有四个参数的两个构造器。
那么我们在配置文件当中,也是可以使用第二个构造方法来赋值的:
测试一下:
结果是:
正常的。没有报错。
但是s3当中的90,我是想要赋值给score的,但是赋值给了age。MLGB。
这是为什么呢?
这是因为你写的90,90就是一个int类型。所以赋值给了age。
我们设置一下属性的index和type。
这个时候,再通过构造方法匹配的时候,就会匹配到正确的构造方法了。
下面是测试结果:
如果使用构造方法赋值的时候,出现了数据的混淆,这个时候就要加上index和type。
这里的index就是bean标签对象当中的index。
这里看到constructor-arg,知道这是构造方法赋值,就可以了。
后面咱们用得最多的,还是property标签。
点击namespaces,点击p。
这个时候,就会发现xml文件当中多了一行:
这个时候,就可以来用p命名空间了。
引入了p命名空间之后,就不需要使用property标签了,直接在bean标签当中,通过p:属性
来进行赋值。
这种方式也记住。
这三种方式,都要知道,真正用的时候,可能就是property的。
这里说的意思是,为属性赋值的时候,可以使用的值。
字面量就是,你能够把这个值,写成字符串的方式的,就叫做字面量。
所有的基本数据类型,以及基本数据类型的包装类,以及string。这些都是字面量。
但是引用数据类型是不可以的。
可以通过value直接赋值的,就是字面量。integer,double,string都可以,这都可以叫做字面量。
在java当中如何表示?
是可以在student当中,创建一个Teacher类型的属性。
大家都做过增删改查,表和表之间的关系,多对一,一对多,一对一,多对多。
学生和老师是多对一的。
在多的这一方,就是学生这一方,设置一个一的属性,就是老师的属性。
一对多的时候。
在一的这一方面,就是老师的这一方,设置一个多的集合,就是学生的集合。
在spring的配置文件当中怎么表示呢?
这个时候,是不能够通过value来赋值的。
value只能够赋值字面量。
不能够使用value。
我们应该怎么做呢?
我们需要创建一个对象,通过对象来给teacher属性赋值。
这个时候,让spring管理一个teacher对象。
设置teacher对象的属性。
这个属性的意思,叫做引用的意思,作用就是引用当前spring管理范围之内的bean的id。
这里ref之后的teacher,表示的就是spring管理范围之内id为teacher的对象。
给属性赋值,第一种叫做字面量,通过value属性,第二种叫做引用类型,通过ref属性。
p命名空间当中也有类似的ref的机制。
按着ctrl键,直接定位到这个地方。
级联大家有没有听说过?
就是一级一级的联动效果。
举个最简单的例子,叫做三级联动。
比如京东,淘宝,美团买东西。选择地址的时候,每选择一级,都是有联动效果的。
选择了省份之后,就要选择地级市,然后就要选择地级市下面的县。
student当中包含teacher对象,teacher对象当中包含tid和tname属性。
测试结果:
这个就是叫做级联属性赋值。属性中包含一些属性。
有没有学过内部类?
内部类有几种写的方式:
内部bean和内部类,不是一个意思。
大家感觉哪里的方言最难听懂的。山西的方言很难听懂。
一个村和一个村都不一样。
原来同事山西的,出去玩接电话,根本听不懂。
以后尽量说普通话。
念个html,都是he,te,mo,le。
安装oracel的时候,有个默认的用户,叫做scott,有人就年做斯考特。
说起来oracle,不得不吐槽,关系型数据库,这东西应用价值非常高。咱们用mysql,以后可以接触oracle。
大公司都是用oracle。前几年来钱慢,都用mysql,但是性能不行,开源免费。
oracle本来性能就很强大,想在公司里面用。好几百万。
真的就是这样的。但是咱们学习的时候,装普通的oracle,特别脆弱,特别大。
跟你电脑性能没有特别大关系,最少20分钟安装。
虽然mysql卸载就够麻烦的了,还要删除注册表什么的。
oracle卸载最少也要10分钟左右。
就是这样的。
mysql就一个服务。
oracle装完,一共是7、8个服务。有三个启动才能用的。
杨博超当时电脑是4G内存,360的加速球,直接飙99%。
写一行代码,咔咔打完了,半分钟,打的内容才会一点一点出来。
oracle非常脆弱,没过两天,一开机,说没了。网上说360把它当病毒删除了,特别麻烦。
教学过程中,也是,没两天就没了。
能删除oracle的东西太多了,比如网游加速器。
网游加速器原理就是把你不用的服务,关闭掉。
安装oracle之前,先检查学生有没有安装网游加速器。
再创建一个student的bean,给teacher属性赋值的时候,还有内部bean的写法:
例如上面的图中,我们可以在ref引用对象的时候,直接写一个内部的bean。
定义在某个bean内部的bean,只能够在当前bean中使用。
之前我们一直都是在讲依赖注入的内容,DI就是给属性赋值。
如果说,咱们学过的集合:list、set、map还有数组,咱们怎么用spring实现呢?
在teacher对象当中定义一个list集合。
集合的根接口是collection,collection跟list和set的关系,是什么?
list和set是继承了collection,list和set也是接口。
接口和接口只能继承。
类和类之间只能继承。
类和接口之间才能够实现。
list这个接口,根据实现方式,有几个实现类,三个。ArrayList、LinkList、Vector。
set是有一个hashSet还有一个TreeSet。
HashSet按照hash值排序。
TreeSet按照自然序升序排序。
Map是有两个实现类,hashMap和hashTable。
hashTable用得不多,但是hashTable有个子类,叫做Properties,这个类用得比较多。
这个Properties类最基本的功能,跟hashTable一样,都是键值对存在。
在java当中有Properties文件,Properties类,就是操作Properties文件,有两个方法,store是保存,load是加载。
这个集合用来存储老师教的班级。
然后在spring当中,通过配置管理teacher这个对象。
测试一下:
在编程语言当中,如果你写四个0,数字前面的0是没有意义的,数字后面的0才是有意义的。
大家学io流的时候,从文件当中读取内容的时候,读出来的是什么?
比如说字节流,一次可以只读一个字节,当然你也可以把它放在一个数组当中。
一次只读一个字节的情况,通过read方法返回值是int类型,代表的是字节对应的ASCII码。
一个字节占8位,一个int类型相当于4个字节,就是32位。
这里面就有一个过程,就是需要把你读出来的8位,转换成为32位。
怎么转换,前面加24个0。
这就叫做“高24位补0,低8位取值”。
一个老师可以有多个学生。
大家都做个什么项目。
做过多对一的吗?
做过单表的增删改查。
多对一的增删改查。
一对多的增删改查。
表关系就四种。
如果在Teacher对象当中设置,如上的student的list对象,可以吗?
spring进行set注入的时候,找到的,并不是类当中的属性名,而是找到的对应的set方法的名字。
按照正规的命名方法,set和get的方法名字,应该是这样的:
所以,如果你取名的时候,是类似sList这种名字的话,自动生成的set和get方法的方法名字,是不满足规则的。
所以,如果你真的叫做sList,你自动生成了set和get方法之后,没有修改名字,那么你的set和get根本就没有效果。
咱们可以尝试一下。
我们上面不修改set和get方法的情况下,直接在spring当中配置bean对象,类似这样:
配置的时候,直接报错。报错说明,里面没有任何一个set方法能够为这个sList属性赋值。
结论就是,实体类当中起名字的时候,属性绝对不能够使用sList这种名字。
这个list标签当中应该放的是,student对象,能够用字面量解决吗?不能够的。
对引用数据类型的赋值,可以使用ref,可以使用内部bean。
测试的效果是这样的:
这里就是操作list集合的方式,spring管理的方式。
spring管理数组,spring管理set,要去尝试一下。
其实也没有啥好尝试的,文档当中写的都有。
算了,还是讲解一下吧。
为数组属性赋值,可以使用array标签,也可以使用list标签。
为什么呢?
arrayList的底层用的就是数组。
value给字面量赋值。
ref或者bean标签给引用数据类型赋值。
map比较学习的list或set都比较复杂。
因为map当中的元素,都有键值组成。
给Teacher对象,设置一个map属性。
键写成编号,值写成名字。
然后开始配置spring配置文件。
测试一下:
我们上面对bean的集合属性,的处理方法是,在bean当中通过list标签,array标签,set标签,map标签构建对应的集合。
还有其他方法吗?
能够在properties当中,通过ref来引用list,array,set,map对象吗?
也就是说,能够在spring内部直接创建和管理list,array,set,map对象吗?
如果我们想要使用ref,或者说,我们想要spring直接管理一个list对象。
我们需要这样写:
需要用到util工具。
c:foreach,在jsp中使用c标签的时候,见过prefix。
测试一下:
十月 02, 2021 12:35:07 上午 org.springframework.context.support.ClassPathXmlApplicationContext prepareRefresh
信息: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@4783da3f: startup date [Sat Oct 02 00:35:07 CST 2021]; root of context hierarchy
十月 02, 2021 12:35:07 上午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
信息: Loading XML bean definitions from class path resource [beans-di.xml]
Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 't1' defined in class path resource [beans-di.xml]: Initialization of bean failed; nested exception is org.springframework.beans.ConversionNotSupportedException: Failed to convert property value of type 'java.util.ArrayList' to required type 'java.util.ArrayList' for property 'students'; nested exception is java.lang.IllegalStateException: Cannot convert value of type [java.util.ArrayList] to required type [com.atguigu.spring.test.Student] for property 'students[0]': no matching editors or conversion strategy found
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:547)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:475)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:304)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:228)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:300)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:195)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:700)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:760)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:482)
at org.springframework.context.support.ClassPathXmlApplicationContext.(ClassPathXmlApplicationContext.java:139)
at org.springframework.context.support.ClassPathXmlApplicationContext.(ClassPathXmlApplicationContext.java:83)
at com.atguigu.spring.test.TestBySpring.main(TestBySpring.java:10)
Caused by: org.springframework.beans.ConversionNotSupportedException: Failed to convert property value of type 'java.util.ArrayList' to required type 'java.util.ArrayList' for property 'students'; nested exception is java.lang.IllegalStateException: Cannot convert value of type [java.util.ArrayList] to required type [com.atguigu.spring.test.Student] for property 'students[0]': no matching editors or conversion strategy found
at org.springframework.beans.BeanWrapperImpl.convertIfNecessary(BeanWrapperImpl.java:473)
at org.springframework.beans.BeanWrapperImpl.convertForProperty(BeanWrapperImpl.java:509)
at org.springframework.beans.BeanWrapperImpl.convertForProperty(BeanWrapperImpl.java:504)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.convertForProperty(AbstractAutowireCapableBeanFactory.java:1502)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1461)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1197)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:537)
... 11 more
Caused by: java.lang.IllegalStateException: Cannot convert value of type [java.util.ArrayList] to required type [com.atguigu.spring.test.Student] for property 'students[0]': no matching editors or conversion strategy found
at org.springframework.beans.TypeConverterDelegate.convertIfNecessary(TypeConverterDelegate.java:267)
at org.springframework.beans.TypeConverterDelegate.convertToTypedCollection(TypeConverterDelegate.java:537)
at org.springframework.beans.TypeConverterDelegate.convertIfNecessary(TypeConverterDelegate.java:202)
at org.springframework.beans.BeanWrapperImpl.convertIfNecessary(BeanWrapperImpl.java:458)
... 17 more
这个错误的类型,叫做:Cannot convert value of type。
这是类型转换的问题,不能够将list转换成为student。
咱们这里的配置是要将list赋值给students属性的。
这个属性是一个list集合,里面放置的是student对象。
通过这个错误,简单判断出来,当我拿着list标签定义的这个list集合,给实体类的list属性赋值的时候,出现了类型转换的问题。
基本数据类型当中的,小转大,是自动转换。大转小,是需要强制转换。
引用数据类型的时候,可以类型转换吗?通过子类的构造方法,实现类的构造方法,能够创造父类的对象,或者是接口的对象。
这个就是转换。
然后能够将上转型对象,强制转换成子类对象,这个就是强制转换。
util:list当中的list标签定义的list对象,是无论如何都不能够转换成为student对象的。他们两个对象之间没有继承,也没有实现的问题。
util:list本身代表的就是一个集合,这个util:list当中的元素,就是student元素了。
去掉util:list当中的list标签之后,就测试正常了:
utils可以操作map,可以操作set,也可以操作properties。
properties和map不一样吗?
不一样的。虽然说map是接口,实现类有一个hashTable,hashTable有一个子类叫做Properties,Properties当中的键和值,都只能够是字符串类型。但是map的键值都可以是object类型,代表的是任意类型。
map当中一个entry代表的是一个键值对。
Teacher对象当中有list类型的属性,也有map类型的属性:
我们都可以在spring的配置文件当中进行DI,使用utils。
factory是工厂,bean是对象,factoryBean就是对象工厂。
spring当中的IOC,用的是什么设计模式呢?
就是工厂模式。
最底层的接口,叫做BeanFactory,就是工厂模式。
我们不在乎他们是怎么为我们创建的对象。我们需要对象的时候,直接从工厂当中获取就可以了。
大家学过什么?
单例,工厂。
工厂模式就是很简单:来隐藏类创建的过程。创建对象的时候,不需要自己去创建,通过工厂去获取。
至于类创建的过程,去工厂当中体现,不在我们获得对象的时候,体现。
明天我们就要学习一个代理模式。
spring当中的AOP用的,就是代理模式。
这个也是非常重要的,也是有一定的难度的。
明天所写的代码,能够记住就记住,记不住就背下来。
FactoryBean是一个接口,我们创建一个类,实现了这个接口,那么这个类,就是FactoryBean。
用法是怎么样呢?
然后我们需要让我们的工厂类,实现FactoryBean这个接口:
这个接口是有泛型的,泛型就是我们的工厂是要创建什么类型的对象的。我们这里是Car类型的。
这里的错误,解决的时候,有几种方式呢?
为什么报错了,因为现在实现这个接口的,是一个普通的类。实现就相当于另类的继承。
实现一个接口,接口当中的抽象方法也会,继承给它的实现类。
这个实现类当中有三个抽象方法。普通类当中是不能够存在抽象方法的。
所以报错了。
第一种解决的方法:加上abstract关键字,把普通类,变成了抽象类。
第二种解决方法:普通类当中不能够存在抽象方法,我们就对抽象方法进行重写。
第一个方法,叫做getObject,获取对象的方法。
第二个方法,叫做getObjectType,获取对象类型。所属类。
第三个方法,是否为单例的。如果返回false不是单例,如果返回true,是单例。
奥迪就是买灯送车,奥迪灯太亮了。
这是返回对象类型。
这是判断对象,是否是单例,默认为false。
在配置文件当中,我不需要创建car的对象,我们把car对象的创建,交给了工厂bean。
这个结果,是我想要的结果,但是有点问题,我们getBean的时候,写的是factory,factory代表的是工厂bean。
按照之前的普通bean的经验,通过getBean获得的是哪个id的bean,一定是bean的class对应的对象。
我们现在拿到的,不是工厂bean,我们获取的是工厂bean创建的bean对象。
这就是我们spring当中,创建的第二种bean对象,叫做工厂bean。
虽然我们bean的class是工厂的全限定名,最终获取的bean,是工厂创建的对象。也就是工厂当中getObject方法返回的对象。