Spring框架-IoC核心
spring FrameWork
springBoot+springCloud+springCloud Data Flow
一:spring的两大核心机制:
- IoC :工厂模式
- AOP:代理模式
1:Ioc
Ioc是Spring是框架的灵魂,控制反转。
Student student = new Student();
lombok 可以帮助开发这者自动生成get set 方法..
在idea中使用必须安装插件
@Data注解
@AllArgsConstructor注解全参的构造
@NoArgsConstructor注解构造无参
设置mavend的版本太低:
- file - projectStructure.. - Modules - Language Level:jdk8以上
- File --> Settings --> Build,Execution,Deployment --> Compiler --> java Compiler
开发过程:
- 创建Maven工程,pom.xml导入依赖。
org.springframework
spring-context
5.2.3.RELEASE
- 在resources路径下创建spring.xml
3.IoC容器通过读取spring.xml配置文件,加载bean标签来创建对象
4.调用API来获取IoC中的已经创建的对象
//传统的开发方式是手动开发对象
// Student a = new Student();
// System.out.println(a);
//IoC容器自动创建对线,开发者只需要取出对象即可
ApplicationContext applicationContext =new ClassPathXmlApplicationContext("spring.xml");
Student student = (Student)applicationContext.getBean("student");
System.out.println(student);
}
IoC容器创建Bean的两种方式:
无参构造
给成员变量赋值(原理是利用set 方法修改的)
IoC取对象:id取
Student student = (Student)applicationContext.getBean("student");实体类的实例类取
Student student = (Student)applicationContext.getBean(Student.class);实体类有多个抛异常
有参构造
取对象:
ApplicationContext applicationContext =new ClassPathXmlApplicationContext("spring.xml");
Student student = (Student)applicationContext.getBean("student1");
// Student student = (Student)applicationContext.getBean(Student.class);
System.out.println(student);
bean中包含特殊字符可以:
<bean id ="classes" class="com.southwind.entity.Classes">
<property name="id" value="1">property>
<property name="name">
<value>]]>value>
property>
bean>
IoC Di
Di 指的是bean之间的依赖注入,设置对象之间的级联关系
Classes:
package com.southwind.entity;
import lombok.Data;
@Data
public class Classes {
private Integer id;
private String name;
}
Student:
package com.southwind.entity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Student {
private Integer id;
private String name;
private Integer age;
private Classes classes;
}
spring-di.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id ="classes" class="com.southwind.entity.Classes">
<property name="id" value="1">property>
<property name="name" value="1班">property>
bean>
<bean id ="student" class="com.southwind.entity.Student">
<property name="id" value="1">property>
<property name="name" value="张三">property>
<property name="age" value="18">property>
<property name="classes" ref="classes">property>
bean>
beans>
Test2:
package com.southwind.test;
import com.southwind.entity.Classes;
import com.southwind.entity.Student;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test2 {
public static void main(String[] args) {
//IoC容器自动创建对线,开发者只需要取出对象即可
ApplicationContext applicationContext =new ClassPathXmlApplicationContext("spring-di.xml");
// String[] names = applicationContext.getBeanDefinitionNames();
// for (String name:names){
// System.out.println(name);
// }
Student student = (Student)applicationContext.getBean("student");
Classes classes =(Classes)applicationContext.getBean("classes");
System.out.println(student);
}
}
Bean对象的级联学要使用ref属性来完成映射,而不能直接使用value否值会抛出类型转化异常:
Classes:
package com.southwind.entity;
import lombok.Data;
import javax.swing.*;
import java.util.List;
@Data
public class Classes {
private Integer id;
private String name;
private List studentList;
}
spring-di.xml:
<bean id ="classes" class="com.southwind.entity.Classes">
<property name="id" value="1">property>
<property name="name">
<value>]]>value>
property>
<property name="studentList">
<list>
<ref bean="student" >ref>
<ref bean="student1" >ref>
list>
property>
bean>
但是要注意不能闭环
spring中的Bean
bean 是根据scope 来生成的,表示bean的作用域,scope有4种“
- singleton ,单例,表示通过Spring容器获取对象的唯一性 默认
(无论取不取,只要加载IoC容器,就创建对象) - prototype, 原型,表示通过Spring容器获取的对象是不同的
(如果不取Bean就不创建对象,取几个就创建几个对象) - request ,请求,表示在一次HTTP请求内有效
- session ,会话,表示在一个用户内有效
requestion、session仅在web中有效
Spring的继承
Spring的继承不同于Java ,区别:java中的继承是真对类的,SPring中的继承是针对对象的(Bean)
Spring的继承中,子Bean可以以继承父Bean中的值
通过parent设置继承关系,同时值bean的值来继承和覆盖
<bean id="user1" class="com.southwind.entity.User" scope="prototype" >
<property name="id" value="1">property>
<property name="name" value="张三">property>
bean>
<bean id="user" class="com.southwind.entity.User" scope="prototype" parent="user1">
<property name="name" value="李四">property>
bean>
即使是两个不同的类,只是赋值。(属性名一样必须,不一样抛异常)(只要成员变量一样就行)
Spring的依赖:
用来设置两个Bean的顺序
IoC容器默认情况是通过spring.xml中bean的配置顺序来决定创建的顺序
在不修改spring.xml来depends-on=""修改
"user" class="com.southwind.entity.User" depends-on="student">
bean>
"student" class="com.southwind.entity.Student">bean>
Spring读取外部资源
实际开发中,数据库的资源一般会单独保存起来。一般会保存到后缀为properties的文件中,方便维护和修改,如果Spring加载资源,就需要在spring.xml中读取properties中的资源
xxx.properties
user=root
password=root
url = jdbc:mysql://localhost:3306/library
driverName=com.mysql.cj.jdbc.Driver
spring-xx.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<context:property-placeholder location="classpath:jdbc.properties">context:property-placeholder>
<bean id="dataSource" class="com.southwind.entity.DataSouse ">
<property name="user" value="${user}">property>
<property name="password" value="${password}">property>
<property name="url" value="${url}">property>
<property name="driverName" value="${driverName}">property>
bean>
beans>
DataSource:
package com.southwind.entity;
import lombok.Data;
@Data
public class DataSouse {
private String user;
private String password;
private String url;
private String driverName;
}
测试类:
package com.southwind.test;
import com.southwind.entity.DataSouse;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test4 {
public static void main(String[] args) {
ApplicationContext applicationContext =new ClassPathXmlApplicationContext("spring-property.xml");
DataSouse dataSouse = (DataSouse)applicationContext.getBean("dataSource");
System.out.println(dataSouse);
}
}
Spring p 命名空间
p 命名空间简化Bean的配置
Spring-p.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="student" class="com.southwind.entity.Student" p:id="1" p:name="张三">bean>
beans>
测试类:
package com.southwind.test;
import com.southwind.entity.Student;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test5 {
public static void main(String[] args) {
ApplicationContext applicationContext =new ClassPathXmlApplicationContext("spring-p.xml");
Student student = (Student)applicationContext.getBean("student");
System.out.println(student);
}
}
如果和级联一样:也是p:age-ref=""写类
同时也要引入:
xmlns:p="http://www.springframework.org/schema/p"
"http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
Spring的工厂方法:
IoC通过工厂模式创建bean对线有两种方式:
- 静态工厂模式
- 实例工厂模式
区别在与:静态工厂不需要实例化,实例工厂需要实例化
1.静态工厂
实体类Car
package com.southwind.entity;import lombok.AllArgsConstructor;
import lombok.Data;@Data
@AllArgsConstructor
public class Car {
private Integer num;
private String brand;
}创建静态工厂,使用静态工厂方法:
package com.southwind.factory;import com.southwind.entity.Car;
import java.util.HashMap;
import java.util.Map;public class StaticCarFactory {
private static MapcarMap;
static {
carMap=new HashMap<>();
carMap.put(1,new Car(1,"奥迪"));
carMap.put(1,new Car(1,"奥拓"));
}
public static Car getCar(Integer num){
return carMap.get(num);
}
}
3.Spring-xx.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="car1" class="com.southwind.factory.StaticCarFactory" factory-method="getCar">
<constructor-arg value="1">constructor-arg>
bean>
beans>
factory-method 是指向静态方法
constructor-arg value="1” 是指向传入的参数
测试类:
package com.southwind.test;
import com.southwind.entity.Car;
import com.southwind.factory.StaticCarFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test6 {
public static void main(String[] args) {
// Car car = StaticCarFactory.getCar(1);
ApplicationContext applicationContext= new ClassPathXmlApplicationContext("spring-factory.xml");
Car car = (Car)applicationContext.getBean("car1");
System.out.println(car);
}
}
2.实例工厂方法:
1.创建实例工厂类、工厂方法
package com.southwind.factory;
import com.southwind.entity.Car;
import java.util.HashMap;
import java.util.Map;
public class InstanceCarFactory {
private Map carMap;
public InstanceCarFactory(){
carMap= new HashMap<>();
carMap.put(1,new Car(1,"奥迪"));
carMap.put(1,new Car(1,"奥托"));
}
public Car getCar(Integer num){
return carMap.get(num);
}
}
2.spring-xx.xml
<bean id="instanceCarFactory" class="com.southwind.factory.InstanceCarFactory">bean>
<bean id="car2" factory-bean="instanceCarFactory" factory-method="getCar">
<constructor-arg value="1">constructor-arg>
bean>
测试类:
package com.southwind.test;
import com.southwind.entity.Car;
import com.southwind.factory.StaticCarFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test6 {
public static void main(String[] args) {
// Car car = StaticCarFactory.getCar(1);
// ApplicationContext applicationContext= new ClassPathXmlApplicationContext("spring-factory.xml");
// Car car = (Car)applicationContext.getBean("car1");
// System.out.println(car);
// }
// 实例工厂
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-factory.xml");
Car car = (Car) applicationContext.getBean("car2");
System.out.println(car);
}
}
区别:
- 静态工厂方法创建Car对象,不需要创建Car对象,因为静态工厂的静态方法,不需要通过创建对象即可调用。spring-xx.xml中只需要配置一个Bean,即最终的Car即可。
- 实例工厂方法创建Car对象,需要实例化工厂对象,因为getCar()方法是非静态的,就必须通过实例化的对象才能调用,所以就必须创建工厂对象,spring。xml中,要配置两个Bean一个是工厂对象,一个是Car 对象。
Spring IoC 自动装载 autowire:
自动装载是Spring提供的一种更加简单的方式,来完成DI,不需要手动配置property ,IoC容器会自动选择Bean玩成注入。
自动装载俩种:
byName ,通过属性名完成自动装载
byType,通过属性对应的数据类型完成自动装载
byName
1.创建实体类
package com.southwind.entity;import lombok.Data;
@Data
public class Presson {
private Integer Id;
private String name;
private Car car;}
2.在spring.xml中配置Car和Person的Bean,通过自动装载完成依赖注入
<bean id="person" class="com.southwind.entity.Presson" autowire="byName">
<property name="id" value="1">property>
<property name="name" value="张三">property>
bean>
<bean id="car" class="com.southwind.entity.Car">
<constructor-arg name="num" value="1"> constructor-arg>
<constructor-arg name="brand" value="奥迪">constructor-arg>
bean>
测试:
package com.southwind.test;
import com.southwind.entity.Presson;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test7 {
public static void main(String[] args) {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-autowire.xml");
Presson preson =(Presson)applicationContext.getBean("person");
System.out.println(preson);
}
}
byType:
1.实体类
2.在spring.xml中配置Car和Person的Bean,通过自动装载完成依赖注入
<bean id="person" class="com.southwind.entity.Presson" autowire="byType">
<property name="id" value="1">property>
<property name="name" value="张三">property>
bean>
<bean id="car" class="com.southwind.entity.Car">
<constructor-arg name="num" value="1"> constructor-arg>
<constructor-arg name="brand" value="奥迪">constructor-arg>
bean>
注意:
使用byType进行自动装载时,多个会有异常。
Spring IoC基于注解的开发
SpingIoC的作用帮助开发者创建项目中所需要的Bean,同时完成Bean之间的依赖注入关系。DI
实现功能有两种方式:
- 基于xml
- 基于注解
基于注解的配置有两部:
配置自动扫包
添加注解: @Component (默认首字母类第一个字母小写为名字)
package com.southwind.entity;import lombok.Data;
import org.springframework.stereotype.Component;
@Data
@Component
public class Repository {
private DataSouse dataSouse;
}改名字:@Component(value = "myrepo")
package com.southwind.entity;import lombok.Data;
import org.springframework.stereotype.Component;
@Data
@Component(value = "myrepo")
public class Repository {
private DataSouse dataSouse;
}分析注入得到类:
String[] s= applicationContext.getBeanDefinitionNames();
for(String name :s){
System.out.println(name);
}
DI:
package com.southwind.entity;
import lombok.Data;
import org.springframework.stereotype.Component;
@Data
@Component
public class DataSouse {
private String user;
private String password;
private String url;
private String driverName;
}
自动装载:@Autowired(默认时byType)
package com.southwind.entity;
import lombok.Data;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Data
@Component
public class Repository {
@Autowired
private DataSouse dataSouse;
}
要改变为byName()配合 @Qualifier(value="DS")
@Data
@Component
public class Repository {
@Autowired
@Qualifier(value="DS")
private DataSouse dataSouse;
}
实体类中的普通的成员变量可以通过@Value进行赋值
@Data
@Component(value = "DS")
public class DataSouse {
@Value("root")
private String user;
@Value("root")
private String password;
@Value("jdbc:mysql://localhost:3306/library")
private String url;
@Value("com.mysql.cj.jdbc.Driver")
private String driverName;
}
实际开发的使用
实际开发中会将程序分为3层:
- Controller
- Servlet
- Repository(DAO)
关系Controller 调运Servlet 调运 Repository(DAO)
@Component 注解是将标注的类加载到IoC容器中,实际开发中可以分别根据
@Controller 控制层
@Service 业务层
@Repository 持久层
代码:
1.
package com.southwind.Repository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
public interface myRepository {
public String domyRepository(Double score);
}
package com.southwind.Repository.impl;
import com.southwind.Repository.myRepository;
import org.springframework.stereotype.Repository;
@Repository
public class mymyRepositoryImpl implements myRepository {
@Override
public String domyRepository(Double score) {
String result="";
if(score<60){
result="不及格";
}else if(score>=60&&score<80){
result="合格";
}else {
result="优秀";
}
return result;
}
}
2.
package com.southwind.Service;
import org.springframework.stereotype.Component;
public interface myService {
public String doSrvice(Double score);
}
package com.southwind.Service.impl;
import com.southwind.Repository.myRepository;
import com.southwind.Service.myService;
import lombok.Setter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Setter
@Service
public class myServiceImpl implements myService {
@Autowired
private myRepository myRepository;
@Override
public String doSrvice( Double score) {
return myRepository.domyRepository(score);
}
}
3.
package com.southwind.Controller;
import com.southwind.Service.myService;
import lombok.Data;
import lombok.Setter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
@Controller(value = "a")
@Data
public class myControlller {
//客户端请求
@Autowired
private com.southwind.Service.myService myService;
; public String service(Double score){
return myService.doSrvice(score);
}
}
配置:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="com.southwind">context:component-scan>
beans>
测试类:
package com.southwind.test;
import com.southwind.Controller.myControlller;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test9 {
public static void main(String[] args) {
ApplicationContext applicationContext =new ClassPathXmlApplicationContext("spring-annotation.xml");
// String[] s= applicationContext.getBeanDefinitionNames();
// for(String name :s){
// System.out.println(name);
// }
// 客户端请求
myControlller myControlller =(myControlller) applicationContext.getBean("a") ;
String result = myControlller.service(new Double(77));
System.out.println(result);
}
}
Spring IoC的底层实现:
核心技术: XML解析+反射
具体思路:
- 根据需求编写XML文件,配置需要的创建的Bean.
- 编写程序需要的XML文件,获取Bean的相关信息,类,属性,id
- 根据第二步骤获得到的信息,结合反射机制动态的创建对象,同时完成属性的赋值
- 将创建好的bean存入Map集合中,设置key就是bean的id的值,value就是bean的对象
- 提供方法从Map中获得对应的value