Spring 是一种轻量级开发框架,旨在提高开发人员的开发效率以及系统的可维护性。
我们一般说 Spring 框架指的都是 Spring Framework,它是很多模块的集合,使用这些模块可以很方便地协助我们进行开发。这些模块是:核心容器、数据访问/集成,、Web、AOP(面向切面编程)、工具、消息和测试模块。比如:核心容器中的 Core 组件是Spring 所有组件的核心,Beans 组件和 Context 组件是实现IOC和依赖注入的基础,AOP组件用来实现面向切面编程。(2021动力节点)
Spring 是一个 IOC 和 AOP 容器框架。 Spring 容器的主要核心是:• 控制反转( IOC ),传统的 java 开发模式中,当需要一个对象时,我们会自己使用 new 或者 getInstance 等直接或者间接调用构造方法创建一个对象。而在spring 开发模式中, spring 容器 使用了 工厂模式 为我们创建了所需要的对象,不需要我们自己创建了,直接调用 spring 提供的对象就可以了,这是控制反转的思想。• 依赖注入( DI ), spring 使用 javaBean 对象的 set 方法或者带参数的构造方法 为我们在创建所需对象时将其 属性自动设置所需要的值的过程 ,就是依赖注入的思想。• 面向切面编程( AOP ),在面向对象编程( oop )思想中,我们将事物纵向抽成一个个的对象。而在面向切面编程中,我们将一个个的对象某些类似的方面横向抽成一个切面,对这个切面进行一些如 权限控制、事物管理,记录日志 等。公用操作处理的过程就是面向切面编程的思想。 AOP 底层是 动态代理 ,如果是接口采用 JDK 动态代理 ,如果是类采用 CGLIB 方式 实现动态代理。(2022黑马)
Spring 是一个开源框架,为简化企业级应用开发而生。Spring 可以是使简单的JavaBean 实现以前只有EJB 才能实现的功能。Spring 是一个 IOC 和 AOP 容器框架。
Spring 容器的主要核心是:
控制反转(IOC),传统的 java 开发模式中,当需要一个对象时,我们会自己使用 new 或者 getInstance 等直接或者间接调用构造方法创建一个对象。而在 spring 开发模式中,spring 容器使用了工厂模式为我们创建了所需要的对象,不需要我们自己创建了,直接调用spring 提供的对象就可以了,这是控制反转的思想。
依赖注入(DI),spring 使用 javaBean 对象的 set 方法或者带参数的构造方法为我们在创建所需对象时将其属性自动设置所需要的值的过程,就是依赖注入的思想。
面向切面编程(AOP),在面向对象编程(oop)思想中,我们将事物纵向抽成一个个的对象。而在面向切面编程中,我们将一个个的对象某些类似的方面横向抽成一个切面,对这个切面进行一些如权限控制、事物管理,记录日志等公用操作处理的过程就是面向切面编程的思想。AOP 底层是动态代理,如果是接口采用 JDK 动态代理,如果是类采用CGLIB 方式实现动态代理。(硅谷)
面试题:
Spring Core: 基础,可以说 Spring 其他所有的功能都需要依赖于该类库。主要提供 IoC 依赖注入功能。
Spring AOP :提供了面向切面的编程实现。
Spring JDBC : Java数据库连接。
Spring JMS :Java消息服务。
Spring ORM : 用于支持Hibernate等ORM工具。
Spring Web : 为创建Web应用程序提供支持。
Spring Test : 提供了对 JUnit 和 TestNG 测试的支持。(2021动力节点)
IOC:Inversion of Control,翻译过来是反转控制。
之前我们需要用到某个资源 某个对象 需要我们手动去创建他 手动的去访问他 有了spring之后 可以把对象的管理权 ,对象的控制权 完全交给IOC容器 原来是主动获取 现在是被动去接受 spring为我们提供的对象 总结一句话:原来我们要自己创建 现在不用自己 用spring里面的就可以
IOC ( Inversion Of Controll ,控制反转)是一种设计思想,就是将原本在程序中手动创建对象的控制权,交由给 Spring 框架来管理。 IOC 在其他语言中也有应用,并非 Spring 特有。 IOC 容器是 Spring 用来实现 IOC 的载体, IOC 容器实际上就是一个 Map(key, value) , Map 中存放 的是各种对象。将对象之间的相互依赖关系交给 IOC 容器来管理,并由 IOC 容器完成对象的注入。这样可以很大程度上简化应用的开发,把应用从复杂的依赖关系中解放出来。 IOC容器就像是一个工厂一 样,当我们需要创建一个对象的时候,只需要配置好配置文件 / 注解即可,完全不用考虑对象是 如何被创建出来的。在实际项目中一个 Service类可能由几百甚至上千个类作为它的底层,假 如我们需要实例化这个 Service ,可能要每次都搞清楚这个 Service 所有底层类的构造函数,这 可能会把人逼疯。如果利用 IOC 的话,你只需要配置好,然后在需要的地方引用就行了,大大增加了项目的可维护性且降低了开发难度(2022黑马)
双击shift 查找IOC的具体实现
BeanFactory就是IOC容器最根本的实现
ctrl+H 查看子接口或类的继承关系
1.如何把对象交给IOC容器管理
2.如何获取ioc容器
3.如何从ioc容器中获得我们当前所管理的对象
入门准备工作 com.atguigu.spring
spring管理对象, 管理的对象我们叫做组件 也叫做been 所以spring管理对象也可以叫做spring管理been
jar org.springframework spring-context 5.3.1 junit junit 4.12 test 依赖解释:
spring-context中context是上下文的意思
③创建类HelloWorld
对象从类来的
public class HelloWorld {
public void sayHello(){
System.out.println("hello,spring");
}
}
现在要把HelloWorld这个类交给spring
如何交给spring 做法:
④创建Spring的配置文件
⑤在Spring的配置文件中配置bean
解释:
1 为什么要设置class:一个bean对应一个对象 对象从类来 所以我们要通过class,来设置我们当前bean所对应对象的类型
2. 解释
把helloworld类型的对象交给IOC容器管理
@Test
public void test(){
//获取IOC容器
ApplicationContext ioc = new ClassPathXmlApplicationContext("applicationContext.xml");
//获取IOC容器中的bean
HelloWorld helloworld = (HelloWorld) ioc.getBean("helloworld");
helloworld.sayHello();
}
思路:
把对象交给ioc容器来管理,我们获取ioc容器 就能够获取ioc容器中的对象,然后就可以调用对象中的方法
①创建spring_ioc_xml
②引入依赖
jar org.springframework spring-context 5.3.1 junit junit 4.12 test mysql mysql-connector-java 8.0.16 com.alibaba druid 1.0.31
③创建学生类Student package com.atguigu.spring.pojo
package com.atguigu.spring.pojo;
public class Student {
private Integer sid;
private String sname;
private Integer age;
private String gender;
public Student() {
}
public Student(Integer sid, String sname, Integer age, String gender) {
this.sid = sid;
this.sname = sname;
this.age = age;
this.gender = gender;
}
public Integer getSid() {
return sid;
}
public void setSid(Integer sid) {
this.sid = sid;
}
public String getSname() {
return sname;
}
public void setSname(String sname) {
this.sname = sname;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
@Override
public String toString() {
return "Student{" +
"sid=" + sid +
", sname='" + sname + '\'' +
", age=" + age +
", gender='" + gender + '\'' +
'}';
}
}
⑤测试IOCByXMLTest
@Test
public void testIOC(){
//获取IOC容器
ApplicationContext ioc = new ClassPathXmlApplicationContext("spring-ioc.xml");
//获取bean
Student studentOne = (Student) ioc.getBean("studentOne");
System.out.println(studentOne);
}
当前我们只是创建一个对象,并没有为我们对象中的成员变量赋值,所以我们可以获取到对象的 不过对象里面成员变量的值都是null
每个成员变量都有一个默认值,比如基本数据 int是0, double是0.0 引用类型是null
ioc底层是工厂模式,因为他的基本的实现叫做BeanFactory,具体是如何帮我们创建对象 我们在没有学习spring之前,我们要创建对象我们用的是new构造方法,spring是如何帮我们创建对象?
想要获取ioc容器是通过配置文件来获取 所以是根据我们的
总结:在ioc容器中,就是通过反射+工厂模式来帮助我们创建对象,管理对象
因为无参构造是固定的,写法是固定的,有参构造要设置各自成员变量,然后为成员变量进行赋值,所以有参构造可以设置多种方式,可以设置多个重载的方法,里面可以有sid,或者说只有sname或是有sid和sname,所以它并不知道我们的有参构造是什么,但是他知道我们无参构造的样子,我们以后主要有反射 通过反射创建实例化对象用的都是无参构造
总上所述 如果这时我们把无参构造删除后 会出现如下问题:
Caused by: java.lang.NoSuchMethodException: com.atguigu.spring.pojo.Student.
() 没有足够的方法异常,Student方法没有 所以这个报错的意思就是没有无参构造
总结:以后在写一个类的时候 一定要加上无参构造(宁可没有有参也要有无参,当前如果没有设置有参时 无参是默认的 总之一句话 写一个类 一定要写上无参构造)
2.3、实验二:获取bean的三种方式和注意事项
@Test
public void testIOC(){
//获取IOC容器
ApplicationContext ioc = new ClassPathXmlApplicationContext("spring-ioc.xml");
//获取bean
// Student studentOne = (Student) ioc.getBean("studentOne");
Student student = ioc.getBean(Student.class);
System.out.println(student);
}
注意事项:
1 .如果有二个bean 如图 不知道要获取哪一个就会报错 如下
报错如下:
org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'com.atguigu.spring.pojo.Student' available: expected single matching bean but found 2: studentOne,studentTwo
解释:Unique唯一 当前没有一个唯一的并发现异常 我们根据类型来获取Student对象,但是我们现在可有的有二个 studentOne,studentTwo
总结:注意:根据类型获取bean时,要求IOC容器中有且只有一个类型匹配的bean
2 .如果一个bean都没有
报错:
org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.atguigu.spring.pojo.Student' available
当前没有足够的bean并发现异常
@Test
public void testIOC(){
//获取IOC容器
ApplicationContext ioc = new ClassPathXmlApplicationContext("spring-ioc.xml");
//获取bean
//根据id获取
// Student studentOne = (Student) ioc.getBean("studentOne");
//根据类型获取
//Student student = ioc.getBean(Student.class);
//根据id和类型
Student student = ioc.getBean("studentOne", Student.class);
System.out.println(student);
}
id = "helloworldOne" class = "com.atguigu.spring.bean.HelloWorld" > id = "helloworldTwo" class = "com.atguigu.spring.bean.HelloWorld" >
org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying beanof type 'com.atguigu.spring.bean.HelloWorld' available: expected single matching bean butfound 2: helloworldOne,helloworldTwo
让Student实现当前接口
@Test
public void testIOC(){
//获取IOC容器
ApplicationContext ioc = new ClassPathXmlApplicationContext("spring-ioc.xml");
//获取bean
//根据id获取
// Student studentOne = (Student) ioc.getBean("studentOne");
//根据类型获取
//Student student = ioc.getBean(Student.class);
//根据id和类型
//Student student = ioc.getBean("studentOne", Student.class);
//这个是可以的 这个的意思是通过Student类型获取到bean之后 把获取的对象 通过向上转型 赋值给接口对象
Person student = ioc.getBean(Student.class);
System.out.println(student);
}
而我们这题的意思是如下:
@Test
public void testIOC(){
//获取IOC容器
ApplicationContext ioc = new ClassPathXmlApplicationContext("spring-ioc.xml");
//获取bean
//根据id获取
// Student studentOne = (Student) ioc.getBean("studentOne");
//根据类型获取
//Student student = ioc.getBean(Student.class);
//根据id和类型
//Student student = ioc.getBean("studentOne", Student.class);
//这个是可以的 这个的意思是通过Student类型获取到bean之后 把获取的对象 通过向上转型 赋值给接口对象
//Person student = ioc.getBean(Student.class);
//通过接口类型在ioc里面匹配一个baen来进行获取
//可以的 因为是根据类型来找 只要类型能够兼容匹配就可以
//也就是说,我们在ioc容器中配置一个bean后 是可以通过它所继承的父类或所实现的接口 都可以来获取
Person person = ioc.getBean(Person.class);
System.out.println(person);
}
* 获取bean的三种方式: * 1、根据bean的id获取 * 2、根据bean的类型获取 * 注意:根据类型获取bean时,要求IOC容器中有且只有一个类型匹配的bean * 若没有任何一个类型匹配的bean,此时抛出异常:NoSuchBeanDefinitionException * 若有多个类型匹配的bean,此时抛出异常:NoUniqueBeanDefinitionException * 3、根据bean的id和类型获取 * 结论: * 根据类型来获取bean时,在满足bean唯一性的前提下 * 其实只是看:『对象 instanceof 指定的类型』的返回结果 * 只要返回的是true就可以认定为和类型匹配,能够获取到。 * 即通过bean的类型、bean所继承的类的类型、bean所实现的接口的类型都可以获取bean