开始时间:2021-12-14
课程地址
Spring 的核心是控制反转(IoC)和面向切面编程(AOP)。 Spring 是可以在 Java SE/EE 中使用的轻量级开源框架。
Spring 的主要作用就是为代码==“解耦”==,降低代码间的耦合度。 就是让对象和对象(模块和模块)之间关系不是使用代码关联,而是通过配置来说明。即在 Spring 中说明对象(模块)的关系。
Spring优点Spring 是一个框架,是一个半成品的软件。有 20 个模块组成。它是一个容器管理对象,容器是装东西的, Spring 容器不装文本,数字。装的是对象。 Spring 是存储对象的容器。
- 轻量
- 针对接口编程,解耦合
- AOP 编程的支持
- 方便集成各种优秀框架
控制反转(IoC, Inversion of Control),是一个概念,是一种思想。指将传统上由程序代码直接 *** 控的对象调用权交给容器,通过容器来实现对象的装配和管理。控制反转就是对对象控制权的转移,从程序代码本身反转到了外部容器。通过容器实现对象的创建,属性赋值,依赖的管理
- 控制: 创建对象,对象的属性赋值,对象之间的关系管理。
- 反转: 把原来的开发人员管理,创建对象的权限转移给代码之外的容器实现。 由容器代替开发人员管理对象。创建对象,
给属性赋值。 - 正转:由开发人员在代码中,使用new 构造方法创建对象, 开发人员主动管理对象。
当前比较流行的实现方式是依赖注入。
用IoC的作用:目的就是减少对代码的改动, 也能实现不同的功能。 实现解耦合。
Java中创建的对象的方法:
java中创建对象有哪些方式:
- 构造方法 , new Student()
- 反射
- 序列化
- 克隆
- 动态代理
- ioc :容器创建对象
ioc的体现: servlet 参考博客
1: 创建类继承HttpServelt
2: 在web.xml 注册servlet , 使用
myservlet com.bjpwernode.controller.MyServlet1
- 没有创建 Servlet对象, 没有 MyServlet myservlet = new MyServlet()
- Servlet 是Tomcat服务器它能你创建的。 Tomcat也称为容器
Tomcat作为容器:里面存放的有Servlet对象, Listener , Filter对象
1.加入依赖
2.创建类
3.创建Spring配置文件
4.使用容器中的对象
依赖: classA 类中含有 classB 的实例,在 classA 中调用 classB 的方法完成功能,即 classA
对 classB 有依赖。
DI 是ioc的技术实现,
DI(Dependency Injection) :依赖注入, 只需要在程序中提供要使用的对象名称就可以, 至于对象如何在容器中创建,
赋值,查找都由容器内部实现。
spring是使用的di实现了ioc的功能, spring底层创建对象,使用的是反射机制。
spring是一个容器,管理对象,给属性赋值, 底层是反射创建对象。
Spring 框架使用依赖注入(DI)实现 IoC。
Spring 容器是一个超级大工厂,负责创建、管理所有的 Java 对象,这些 Java 对象被称
为 Bean。
创建的前期工作和之前用maven创建module一样
File-New-Project 建立一个空的就行
然后新建module 选择maven-create from archetype 然后选择maven-archetype-quickstart
新建好的module中的pom.xml添加Spring依赖
org.springframework spring-context5.2.5.RELEASE
以及添加插件
maven-compiler-plugin 3.1 15
然后创建beans.xml配置文件
src-main-resources-右键new一个XML configuration File-Spring Config
如果没有Spring config这个选项,一种是没有在pom.xml配置上面说的这个插件
另一个是由于IDEA不是旗舰版
如果都没问题,配置完插件后要刷新一下,才能生效找到这个Spring Config,通过这个xml创建beans.xml
spring的配置文件中
1.beans :是根标签,spring把java对象称为bean。
2.spring-beans.xsd是约束文件,和mybatis指定dtd是一样的。
在beans.xml中声明bean
声明bean ,就是告诉spring要创建某个类的对象
id:对象的自定义名称,唯一值。spring通过这个名称找到对象
class:类的全限定名称(不能是接口,因为spring是反射机制创建对象,必须使用类)
spring就完成 Someservice someservice = new SomeserviceImpl()
spring是把创建好的对象放入到map中, spring框架有一个map存放对象的。
springMap.put( id的值,对象);
例如 springMap.put(“someservice”, new SomeserviceImpl());
比较两种创建对象的方式
@Test public void test01() { //主动创建对象 SomeService service=new SomeServiceImpl(); service.doSome(); } @Test public void test02() { //使用spring容器创建的对象 //1.指定spring配置文件的名称 String config = "beans.xml"; //2.创建表示spring容器的对象, ApplicationContext // ApplicationContext就是表示Spring容器,通过容器获取对象了 // ClassPathXmlApplicationContext:表示从类路径中加载spring的配置文件 ApplicationContext ac = new ClassPathXmlApplicationContext(config); //从容器中获取某个对象, 你要调用对象的方法 //getBean("配置文件中的bean的id值") //转了接口类型才能调用其方法 SomeService service = (SomeService) ac.getBean("someService"); //使用spring创建好的对象 service.doSome(); }
使用spring容器创建的对象
1.指定spring配置文件的名称
2.创建表示spring容器的对象, ApplicationContext
ApplicationContext就是表示Spring容器,通过容器获取对象了
ClassPathXmlApplicationContext:表示从类路径中加载spring的配置文件
从容器中获取某个对象, 你要调用对象的方法
getBean(“配置文件中的bean的id值”)
相当于给key拿value了
spring默认创建对象的时间:在创建spring的容器时,会创建配置文件中的所有的对象。
spring创建对象:默认调用的是无参数构造方法
当有多个spring bean对象时,可以通过以下语句获取对象信息
spring默认调用无参构造
@Test public void test03(){ String config="beans.xml"; ApplicationContext ac = new ClassPathXmlApplicationContext(config); //使用spring提供的方法, 获取容器中定义的对象的数量 int nums = ac.getBeanDefinitionCount(); System.out.println("容器中定义的对象数量:"+nums); //容器中每个定义的对象的名称 String names [] = ac.getBeanDefinitionNames(); for(String name:names){ System.out.println(name); } }
也可以获取非自定义类的对象
比如获得date对象
在bean配置文件中添加语句
//获取一个非自定义的类对象 @Test public void test04() { String config = "beans.xml"; ApplicationContext ac = new ClassPathXmlApplicationContext(config); //使用getBean(); Date my = (Date) ac.getBean("mydate"); System.out.println("Date:" + my); }依赖注入
bean 实例在调用无参构造器创建对象后,就要对 bean 对象的属性进行初始化。
初始化是由容器自动完成的,称为注入。
根据注入方式的不同,常用的有两类: set 注入、构造注入。
set注入set 注入也叫设值注入是指,通过 setter 方法传入被调用者的实例。这种注入方式简单、
直观,因而在 Spring 的依赖注入中大量使用。
创建Student类对象
只需要加set方法,不需要加get方法
package BUPT.ba01; public class Student { private String name; private int age; public void setName(String name) { this.name = name; } public void setAge(int age) { this.age = age; } @Override public String toString() { return "Student{" + "name='" + name + ''' + ", age=" + age + '}'; } }
在resource里面配置
这里即使是int类型,也要加双引号
这是xml文件的要求
通过property来实现赋值,调用的是Student类的set方法
测试方法里面进行测试
package BUPT; import BUPT.ba01.Student; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class AppTest { @Test public void test02() { //使用spring容器创建的对象 //1.指定spring配置文件的名称 String config = "ba01/applicationContext.xml"; //2.创建表示spring容器的对象, ApplicationContext ApplicationContext ac = new ClassPathXmlApplicationContext(config); Student mystudent = (Student) ac.getBean("myStudent"); System.out.println(mystudent); } }
但也要注意,虽然明说是set+属性名这样进行赋值
其实他看的不是Student类里面定义的属性,而是找的对应的set方法
比如我没有定义一个属性叫email
但是我在Student类里面设置了一个方法叫 setEmail()
public void setEmail(String email) { System.out.println("输出的是自定义set方法的email" + email); }
配置文件也给一个
那他依然会自动调用这个方法
因为他找的是property后面这个name 再去Student类里找对应的setName方法
引用类型的赋值在实体类新建一个school类
并设置school类为Student类的一个属性
school类
public class School { private String address; private String name; }
Student类
public class Student { private String name; private int age; public School school; //setName setAge以及toString重写省略了,实际是有的 public void setSchool(School school) { System.out.println("school:" + school); this.school = school; } }
新增配置
此时再修改Student的xml配置
注意引用类型通过ref="id"实现的
构造注入就是调用Student里面的constructor来协助创建对象
Student类里面加一个构造函数
public Student(String name, int age, School school) { this.name = name; this.age = age; this.school = school; }
配置文件中使用constructor
自动注入
只对引用类型有效
- byName:当配置文件中被调用者 bean 的 id 值与代码中调用者 bean 类的属性名相同时,可使用
byName 方式,让容器自动将被调用者 bean 注入给调用者 bean。 - byType:配置文件中被调用者 bean 的 class 属性指定的类,要与代码中调用者 bean 类的某引用类型属性类型同源。即要么相同,要么有 is-a 关系(父子类,或是接口-实现类)。但这样的同源的被调用 bean 只能有一个。多于一个,容器就不知该匹配哪一个了。
我们来看byName的一个示例
在配置bean id时,后面加一个 autowire “byName”
因为我们在Student类里面调用School这个类时是这样初始化的
public School school;
所以我们把这个school 作为School类的id名
让他俩匹配在一起,此时就可以进行自动注入了
再来看byType
将autowire后面的值改为 byType
这种的byType比较好理解,因为用school传school
那么我们再看一种情况
新建一个中学类extends学校类
然后配置文件写下面的内容
可以看到该类属于school类的子类,仍然可以自动注入
但如果有多个子类或者父类子类都写在bean里面,会报错,不知道注入谁
- 每个文件的大小比一个文件要小很多。效率高
- 避免多人竞争带来的冲突。
如果你的项目有多个模块(相关的功能在一起) ,一个模块一个配置文件。
学生考勤模块一个配置文件,张三
学生成绩一个配置文件,李四
多文件的分配方式:
- 按功能模块,一个模块一个配置文件
- 按类的功能,数据库相关的配置一个文件配置文件, 做事务的功能一个配置文件, 做service功能的一个配置文件等
将之前的一个拆分一下
school一个
student一个
然后总的来一个,用来import子配置文件
也能正常使用
在total里面也可以使用通配符来import,放在同一级的目录下,才能读取
这样的话要注意total自身的一个命名,不能把自己也包含进去了,防止自己调用自己
结束时间:2021-12-16
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)