1、什么是Spring
Spring是分层的Java EE的一个轻量级开源框架,它以IoC和AOP为内核,提供了表现层Spring MVC和持久层Spring JDBC以及业务层事务管理等众多的企业级应用技术,还能整合开源世界众多著名的第三方框架和类库,逐渐成为使用最多的Java EE企业应用开源框架。
- IoC:Inversion of Control(控制反转)
- AOP:Aspect Oriented Programming(面向切面编程)
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.2.0.RELEASE</version>
</dependency>
2、构成
3、IOC理论推导
UserDao接口
UserDaoImpl实现类
UserService业务接口
UserServiceImpl业务实现类
在我们之前的业务中,用户的需求可能会影响我们用来的代码,我们需要根据用户的需求去修改用代码,代码量十分庞大,修改一次的成本代价十分昂贵。
我们使用一个Set接口实现
private UserDao dao;
//利用set实现动态值注入
public void setUserDao(UserDao dao) {
this.dao = dao;
}
- 之前,程序是主动创建对象,控制权在程序员手上。
- 使用了set注入后,程序不再具有主动性,而是变成了被动的接收对象!
这种思想,从本质上解决了问题,我们程序员不用再去管理对象的创建了,系统的耦合性大大降低,我们更加专注于业务的实现上,这就是IOC的原型!!!!
4、IOC本质
控制反转IOC(Inversion of Control),是一种设计思想,DI(依赖注入)是实现IOC的一种方法,也有人认为DI只是IOC的另一种说法。没有IOC的程序中 , 我们使用面向对象编程 , 对象的创建与对象间的依赖关系完全硬编码在程序中,对象的创建由程序自己控制,控制反转后将对象的创建转移给第三方,个人认为所谓控制反转就是:获得依赖对象的方式反转了。
采用XML方式配置Bean的时候,Bean的定义信息是和实现分离的,而采用注解的方式可以把两者合为一体,Bean的定义信息直接以注解的形式定义在实现类中,从而达到了零配置的目的。
控制反转是一种通过描述(XML或注解)并通过第三方去生产或获取特定对象的方式。在Spring中实现控制反转的是IoC容器,其实现方法是依赖注入(Dependency Injection,DI)。
5、HelloSpring
创建一个实体类 Hello.java
package pojo;
public class Hello {
private String str;
public String getStr() {
return str;
}
public void setStr(String str) {
this.str = str;
}
@Override
public String toString() {
return "Hello{" +
"str='" + str + '\'' +
'}';
}
}
编写配置文件 beans.xml
注意,在property里面:
ref:引用Spring容器中创建好的对象
value:具体的值,基本数据类型!
<?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
https://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- 使用Spring来创建对象,在Spring中,这些都是Beans-->
<bean id="hello" class="pojo.Hello">
<property name="str" value="Spring"/>
</bean>
</beans>
测试
@Test
public void test(){
//获取Spring的上下文对象
ClassPathXmlApplicationContext contex = new ClassPathXmlApplicationContext("beans.xml");
//我们的对象现在都在Spring中的管理了,我们要使用,直接去里面取出来就可以了
Hello hello = (Hello) contex.getBean("hello");
System.out.println(hello.getStr());
}
控制台输出
6、IOC创建对象的方式
- 使用无参构造,默认!!!
- 假设我们要使用有参构造创建对象
01- 下标赋值
<!--使用下标赋值-->
<bean id="user" class="pojo.User">
<constructor-arg index="0" value="刘老师"/>
</bean>
02-通过类型创建(不建议使用)
<!--通过类型创建(不建议使用)-->
<bean id="user" class="pojo.User">
<constructor-arg type="java.lang.String" value="刘老师"/>
</bean>
03-通过参数名来设置
<!--直接通过参数名来设置-->
<bean id="user" class="pojo.User">
<constructor-arg name="name" value="牛老师"/>
</bean>
总结:在配置文件加载的时候,容器中管理的对象就已经初始化了
7、Spring配置说明
01-别名(alias)
<!--直接通过参数名来设置-->
<bean id="user" class="pojo.User">
<constructor-arg name="name" value="牛老师"/>
</bean>
<!--给user取个别名“user2”-->
<alias name="user" alias="user2"/>
02-Bean的配置
- id:bean的唯一标识符,也就是我们所学的对象名
- class:bean对象所对应的全限命名
- name:也是别名,而且更高级,可以同时取多个别名
<bean id="user" class="pojo.User" name="我是别名,我也是别名"> <constructor-arg name="name" value="牛老师"/> </bean>
03-import
这个import,一般用于团队开发使用,它可以将多个配置文件,导入合并为一个。
假设,现在项目中有多个人开发,这三个人赋值不同的类开发,不同的类需要注册在不同的bean中,我们可以利用import将所有人的beans.xml合并为一个总的!!!
- 张三
- 李四
- 王五
- applicationContext.xml(总的)
使用的时候,直接用总的配置就可以了<import resource="beans1.xml"/> <import resource="beans2.xml"/> <import resource="beans3.xml"/>
8、DI依赖注入
01-构造器注入
前面已经说过了
02-Set注入
【环境搭建】
复杂类型
package pojp;
import lombok.Data;
@Data
public class Address {
private Address address;
}
真实测试对象
package pojp;
import lombok.Data;
import java.util.*;
@Data
public class Student {
private String name;
private Address address;
private String[] books;
private List<String> hobbies;
private Map<String, String> card;
private Set<String> games;
private String wife;
private Properties properties;
}
beans.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="student" class="pojp.Student">
<!--第一种,普通值注入,使用value-->
<property name="name" value="老王"/>
</bean>
</beans>
测试
@Test
public void test(){
ApplicationContext context=new ClassPathXmlApplicationContext("beans.xml");
Student student = (Student) context.getBean("student");
System.out.println(student.getName());
}
【完善注入信息】
<?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="address" class="pojp.Address">
<property name="address" value="江西省"/><!--设置值-->
</bean>
<bean id="student" class="pojp.Student">
<!--第一种,普通值注入,value-->
<property name="name" value="老王"/>
<!--第二种,Bean注入,ref-->
<property name="address" ref="address"/>
<!--第三种,数组注入,ref-->
<property name="books">
<array>
<value>红楼梦</value>
<value>三国演义</value>
<value>水浒传</value>
<value>西游记</value>
</array>
</property>
<!--第四种,List注入-->
<property name="hobbies">
<list>
<value>打篮球</value>
<value>敲代码</value>
</list>
</property>
<!--第五种,Map注入-->
<property name="card">
<map>
<entry key="身份证" value="123"/>
<entry key="银行卡" value="456"/>
</map>
</property>
<!--第六种,Set注入-->
<property name="games">
<set>
<value>LOL</value>
<value>DNF</value>
<value>CSGO</value>
</set>
</property>
<!--第七种,null注入-->
<property name="wife">
<null/>
</property>
<!--第八种,Properties注入-->
<property name="properties">
<props>
<prop key="name">老帅比</prop>
<prop key="password">1234</prop>
</props>
</property>
</bean>
</beans>
03-拓展注入
我们可以使用p命名空间和c命名空间注入
需要导入约束:
p命名空间—>xmlns:p=”http://www.springframework.org/schema/p“
c命名空间—>xmlns:c=”http://www.springframework.org/schema/c“
<?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"
xmlns:c="http://www.springframework.org/schema/c"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--p命名空间注入,可以直接注入属性的值:property-->
<bean id="user" class="pojp.User" p:name="刘某" p:password="123"/>
<!--c命名空间注入,通过构造器注入:construct-args-->
<bean id="user2" class="pojp.User" c:name="徐某" c:password="456"/>
</beans>
04-Bean的作用域
1、单例模式(Spring默认机制)
一个类只实例化一次,通过方法得到的对象,即使对象的名字不同,本质还是同一个
<bean id="" class="" scope="singleton"/>
2、多例模式:每次从容器中get时,都会产生一个新对象,适用于多线程
<bean id="" class="" scope="prototype"/>
3、其余的request,session,application,只能在web开发中使用到,表示对象的生存周期
9、Bean的自动装配
- 自动装配是Spring满足bean依赖的一种方式
- Spring会在上下文中自动寻找,并自动给bean装配属性
在Spring中有三种装配的方式
- 在xml中显示配置
- 在Java中显示配置
- 隐式的自动装配bean【重要】
01-环境搭建
Dog.java
package pojo;
public class Dog {
public void shout(){
System.out.println("汪汪汪!");
}
}
Cat.java
package pojo;
public class Cat {
public void shout(){
System.out.println("喵喵喵!");
}
}
People.java
package pojo;
import lombok.Data;
@Data
public class People {
private Cat cat;
private Dog dog;
private String name;
}
02-ByName自动装配
byName:会自动在容器上下文中查找,和自己对象set方法后面的值对应的beanid!!!
<?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="cat" class="pojo.Cat"/>
<bean id="dog" class="pojo.Dog"/>
<bean id="people" class="pojo.People" autowire="byName">
<property name="name" value="老帅比呀"/>
</bean>
</beans>
03-ByType自动装配
byType:会自动在容器上下文中查找,和自己对象属性类型相同的bean!!!弊端:必须保证类型唯一!!!
<?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="cat" class="pojo.Cat"/>
<bean id="dog" class="pojo.Dog"/>
<bean id="people" class="pojo.People" autowire="byType">
<property name="name" value="老帅比呀"/>
</bean>
</beans>
小结:
- byName的时候,需要保证所有bean的id唯一,并且这个bean需要和自动注入的属性的set方法的值一致!!
- byType的时候,需要保证所有bean的class唯一,并且这bean需要和自动注入的属性的类型一致!!