1. Spring
Spring是一个轻量级的控制反转(IoC)和面向切面(AOP)的容器框架。
2. 控制反转(IoC)和依赖注入(DI)
2.1 工厂模式创建对象
实体类:
@Data
public abstract class Pet {
protected String name;
protected String color;
public abstract void eat();
}
public class Dog extends Pet{
@Override
public void eat() {
System.out.println(this.color+this.name+"吃骨头!");
}
}
public class Cat extends Pet{
@Override
public void eat() {
System.out.println(this.color+this.name+"吃小鱼!");
}
}
对象工厂:
public class PetFactory {
public static Pet createInstance(String type,String name,String color) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
Pet pet = null;
Class<?> aClass = Class.forName("com.entity."+type);
pet =(Pet)aClass.newInstance();
pet.setName(name);
pet.setColor(color);
return pet;
}
}
测试:
@Test
public void petTest() throws IllegalAccessException, InstantiationException, ClassNotFoundException {
Scanner scanner = new Scanner(System.in);
System.out.println("宠物的类型:");
String clsName = scanner.next();
System.out.println("宠物名:");
String name = scanner.next();
System.out.println("宠物颜色:");
String color = scanner.next();
Pet pet = PetFactory.createInstance(clsName,name,color);
pet.eat();
}
2.2 Spring IoC(Inversion of Control)
IoC:使用spring框架帮我们进行对象管理(对象的创建,维护对象之间的关系)的模式;侧重于说明对象创建方式的改变;原来写程序需要对象了就 new 一个,控制权在程序,现在我们创建对象交给spring容器来管理,由spring帮我们创建。
2.2.1 spring的IoC操作
①把对象的创建交给spring进行管理;
②IoC操作的两种方式:
a. xml配置文件方式
<bean class="com.entity.Dog"/>
b.IoC注解方式
@Component , @Service , @Repository , @Controller
2.2.2 IoC底层实现技术
a.xml配置文件;
b.dom4j解决xml;
c.设计模式(工厂,模板,单例...)
d.反射
2.2.3 使用spring的步骤
①导入jar包
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.18</version>
</dependency>
②创建类
public class Student {
public void introduce(){
System.out.println("我是一名学生!");
}
}
③创建spring配置文件,配置bean
spring核心配置文件的名称和位置不固定,建议放在src下,建议名字 applicationContext.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 class="com.entity.Student"/>
</beans>
④测试
@Test
public void stuTest(){
//创建spring容器对象
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
//通过spring容器获取在其中定义过的bean对象,由此实现了控制反转
Student student = ac.getBean(Student.class);
student.introduce();
}
2.2.4 spring的bean管理(xml方式)
Bean实例化的方式:
①spring中通过配置文件创建对象;
②bean实例化的三种方式:
a.使用类中的无参构造创建(没有无参构造hui)
<bean class="com.entity.Student"/>
<!--使用id作为唯一标识-->
<bean id="stu" class="com.entity.Student"/>
<!--name也是给对象进行标识-->
<bean name="stu1 stu2" class="com.entity.Student"/>
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
Student stu2 = (Student)ac.getBean("stu");
System.out.println(stu2);
Student stu3 = (Student) ac.getBean("stu1");
System.out.println(stu3);
Student stu4 = ac.getBean("stu2",Student.class);
System.out.println(stu4);
stu1,stu2 是同一个对象
b. 使用静态工厂创建
在类中先创建静态方法,返回对象
静态工厂类:
public class StudentFactory {
public static Student createStu(){
return new Student();
}
}
xml配置静态工厂:
<bean id="staticFac" class="com.factory.StudentFactory" factory-method="createStu"/>
测试:
Student stu5 = (Student) ac.getBean("staticFac");
c.使用实例工厂创建
工厂:
public class Factory {
public Student createStu(){
return new Student();
}
}
配置:
<bean id="fac" class="com.factory.Factory"/>
<bean id="s" factory-bean="fac" factory-method="createStu"/>
测试:
Student stu6 = (Student) ac.getBean("s");
System.out.println(stu6);
2.2.5 Bean标签常用属性
①id:给对象起名称,任意,必须唯一;
②class属性:创建对象所在类的全路径,使用构造创建对象,必不可少;
③name:别名,和id作用一样,可以起多个,空格分割;
④scope:取值 singleton(单例),prototype(多例),request,session,global-session;
⑤lazy-init:懒加载(可以配置全局的懒加载 default-lazy-init = ”true“ );
⑥生命周期: init-method(初始化) 和 destory-method(销毁)
④scope 测试:
@Test
public void facTest(){
ApplicationContext ac = new ClassPathXmlApplicationContext("spring-2.xml");
Student stu1 = ac.getBean(Student.class);
System.out.println(stu1);
Student stu2 = ac.getBean(Student.class);
System.out.println(stu2);
Student stu3 = ac.getBean(Student.class);
System.out.println(stu3);
Student stu4 = ac.getBean(Student.class);
System.out.println(stu4);
Student stu5 = ac.getBean(Student.class);
System.out.println(stu5);
}
多例:
<bean class="com.entity.Student" scope="prototype"/>
单例(不写默认也是单例):
<bean class="com.entity.Student" scope="singleton"/>
自己实现单例模式:
public class Student {
private static Student student;
private Student(){}
public static Student createStudent(){
if(student==null){
student = new Student();
}
return student;
}
public void introduce(){
System.out.println("我是一名学生!");
}
}
⑤懒加载:
默认情况下,只针对单例模式,在创建 ApplicationContext 时,就创建了其中的对象;配置后,在使用该对象时才创建。
⑥生命周期:
<bean class="com.entity.Student" scope="singleton" init-method="introduce" destroy-method="close"/>
public class Student {
public Student(){
System.out.println("创建了一名学生!");
}
public void introduce(){
System.out.println("我是一名学生!");
}
public void close(){
System.out.println("再见了!");
}
}
@Test
public void Test(){
ApplicationContext ac = new ClassPathXmlApplicationContext("spring-2.xml");
((ClassPathXmlApplicationContext)ac).close();
}
在多例模式下,destory-method 不会调用。
2.2.6 BeanFactory和ApplicationContext
BeanFactory是一个接口,是IOC容器的核心,负责实例化,配置和管理bean的生命周期;
ApplicationContext是BeanFactory的子接口,提供更多面向实际应用的功能。
使用 BeanFactory 获取对象:
@Test
public void BeanFactoryTest(){
Resource re = new ClassPathResource("spring-2.xml");
BeanFactory bf = new XmlBeanFactory(re);
Student stu = bf.getBean(Student.class);
System.out.println(stu);
}
2.3 spring DI(Dependency Injection)
依赖注入,侧重于说明维护对象之间的关系;
2.3.1 使用setter设置值(最常用)
@Data
public class Student {
private String name;
private String sex;
private Integer age;
private Double tall;
private List<String> hobbies;
}
<bean id="stu" class="com.wen.Student">
<property name="name" value="张三"/>
<property name="sex" value="男"/>
<property name="age" value="20"/>
<property name="tall" value="1.7"/>
<property name="hobbies">
<list>
<value>篮球</value>
<value>钢琴</value>
<value>学习</value>
</list>
</property>
</bean>
2.3.2 使用构造方法设置值
@Data
public class Student {
private String name;
private String sex;
private Integer age;
private Double tall;
private List<String> hobbies;
public Student() {
}
public Student(String name, String sex, Integer age, Double tall, List<String> hobbies) {
this.name = name;
this.sex = sex;
this.age = age;
this.tall = tall;
this.hobbies = hobbies;
}
}
<bean id="stu" class="com.wen.Student">
<constructor-arg name="name" value="张三"/>
<constructor-arg name="sex" value="男"/>
<constructor-arg name="age" value="20"/>
<constructor-arg name="tall" value="1.7"/>
<constructor-arg name="hobbies">
<list>
<value>篮球</value>
<value>钢琴</value>
<value>学习</value>
</list>
</constructor-arg>
</bean>
2.3.3 使用接口注入(spring 4.0 以后不支持)
为属性赋值两个关键字(配合setter和构造使用):
①value:用于设置普通属性的数据(基本类型,字符串);
②ref : 用于设置对象类型的数据。
司机:
@Data
public class Driver {
private String name;
private CarB car;
}
车:
@Data
public class CarB {
private String brand;
private Integer price;
private Double speed;
}
spring:
<bean id="driver" class="com.entity.Driver">
<property name="name" value="张三"/>
<property name="car" ref="car"/>
</bean>
<bean id="car" class="com.entity.CarB">
<property name="brand" value="宝马"/>
<property name="price" value="300000"/>
<property name="speed" value="75.0"/>
</bean>