目录
使用idea学习,首先要先导入jar包:
一、什么是IOC?
1.控制反转,把对象创建和对象之间的调用的操作交给了Spring管理
2.使用IOC可以降低耦合度
二、IOC底层原理:
1.xml解析
2.工厂模式
3.反射机制
三、IOC容器
Spring提供了IOC容器的两种实现方法
1.BeanFactory:IOC容器基本实现,是 Spring 内部的使用接口,不提供开发人员进行使用
* 加载配置文件时候不会创建对象,在获取对象(使用)才去创建对象
2.ApplicationContext:BeanFactory 接口的子接口,提供更多更强大的功能,一般由开发人 员进行使用
* 加载配置文件时候就会把在配置文件对象进行创建
四、IOC操作Bean管理:
Bean管理分为两部分:(1)Spring创建对象 (2)Spring注入属性
Bean管理的操作有两种方式:(1)基于xml配置文件的实现方式 (2)基于注解的实现方式(这个比较方便,用的也多)
xml方式:
创建对象的配置操作:
①在Spring配置文件中,使用bean标签,标签里面添加响应的属性,实现对象的创建
<bean id="user" class="com.haiyu.spring.User"></bean>
②bean标签中的常用属性:
id属性:唯一标识(这里就是实例化以后的对象名)
class属性:类路径(这里就是要实例化的类的路径)
属性注入的配置操作:
方法一:DI:依赖注入,其实是调用了类中的set()。
在bean标签的中间使用property标签来配置:(可以配置多个)
<property name="uname" value="haiyu"></property>
方法二:使用有参数的构造器进行注入
在bean标签的中间使用constructoy-arg标签来配置:(可以配置多个)
<constructor-arg name="uname" value="haiyu"></constructor-arg>
1、 如果是一个类中调用了另一个类,此时属性的注入是一个类的对象:那就需要这样:(外部bean)
<bean id="emp" class="com.atguigu.spring5.bean.Emp">
<property name="dept" ref="dept"></property>
</bean>
<bean id="dept" class="com.atguigu.spring5.bean.Dept">
<property name="dname" value="财务部"></property>
</bean>
也可以这样(内部bean)
<bean id="emp" class="com.atguigu.spring5.bean.Emp">
<property name="dept">
<bean id="dept" class="com.atguigu.spring5.bean.Dept">
<property name="dname" value="安保部"></property>
</bean>
</property>
</bean>
2、注入数组类型的属性:注入List类型的属性:注入Map类型的属性:注入Set类型的属性(相似)
<bean id="stu" class="com.atguigu.spring5.collectiontype.Stu">
<!--数组类型属性注入-->
<property name="courses">
<array>
<value>java 课程</value>
<value>数据库课程</value>
</array>
</property>
<!--list 类型属性注入-->
<property name="list">
<list>
<value>张三</value>
<value>小三</value>
</list>
</property>
<!--map 类型属性注入-->
<property name="maps">
<map>
<entry key="JAVA" value="java"></entry>
<entry key="PHP" value="php"></entry>
</map>
</property>
<!--set 类型属性注入-->
<property name="sets">
<set>
<value>MySQL</value>
<value>Redis</value>
</set>
</property>
</bean>
3、此时如果有相同的集合需要注入,那xml文件将会很长
所以:在Spring配置文件中引入名称空间util:
<?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:util="http://www.springframework.org/schema/util" //这里,照着上面的改
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util.xsd"> //这里
再使用这个util标签完成list集合的注入:
<util:list id="bookList">
<value>易筋经</value>
<value>九阴真经</value>
<value>九阳神功</value>
</util:list>
<bean id="book" class="com.atguigu.spring5.collectiontype.Book">
<property name="list" ref="bookList"></property>
</bean>
4、Spring有两种类型bean,一种是普通bean,另一种是工厂bean(FactoryBean)
①普通 bean:在配置文件中定义 bean 类型就是返回类型
②工厂 bean:在配置文件定义 bean 类型可以和返回类型不一样
第一步 创建类,让这个类作为工厂 bean,实现接口 FactoryBean
第二步 实现接口里面的方法,在实现的方法中定义返回的 bean 类型
public class MyBean implements FactoryBean<Course> {
//定义返回 bean
@Override
public Course getObject() throws Exception {
Course course = new Course();
course.setCname("abc");
return course;
}
@Override
public Class<?> getObjectType() {
return null;
}
@Override
public boolean isSingleton() {
return false;
}
}
配置
<bean id="myBean" class="com.atguigu.spring5.factorybean.MyBean">
</bean>
此时,getBean()返回值就是工厂bean中泛型的类型
public void test3() {
ApplicationContext context =
new ClassPathXmlApplicationContext("bean3.xml");
Course course = context.getBean("myBean", Course.class);
System.out.println(course);
}
5、在 Spring 里面,默认情况下,bean 是单实例对象
6、如何设置单实例还是多实例
①在 spring 配置文件 bean 标签里面有属性(scope)用于设置单实例还是多实例
②scope 属性值
第一个值 默认值,singleton,表示是单实例对象
第二个值 prototype,表示是多实例对象
<bean id="user" class="com.haiyu.spring.User" scope="prototype">
<property name="list" ref="userList"></property>
</bean>
③singleton 和 prototype 区别
第一 singleton 单实例,prototype 多实例
第二 设置 scope 值是 singleton 时候,加载 spring 配置文件时候就会创建单实例对象 设置 scope 值是 prototype 时候,不是在加载 spring 配置文件时候创建 对象,在调用 getBean 方法时候创建多实例对象
7、xml自动装配:根据指定装配规则(属性名称或者属性类型),Spring 自动将匹配的属性值进行注入
①根据属性名称自动注入
<bean id="emp" class="com.atguigu.spring5.autowire.Emp" autowire="byName">
<!--<property name="dept" ref="dept"></property>-->
</bean>
<bean id="dept" class="com.atguigu.spring5.autowire.Dept"></bean>
②根据属性类型自动注入
<bean id="emp" class="com.atguigu.spring5.autowire.Emp" autowire="byType">
<!--<property name="dept" ref="dept"></property>-->
</bean>
<bean id="dept" class="com.atguigu.spring5.autowire.Dept"></bean>
注解方式:
1、Spring 针对 Bean 管理中创建对象提供注解
(1)@Component
(2)@Service
(3)@Controller
(4)@Repository
上面四个注解功能是一样的,都可以用来创建 bean 实例
2、实现对象创造
第一步:引入依赖
第二步:开启组件扫描
<context:component-scan base-package="com.haiyu.spring"></context:component-scan>
第三步 创建类,在类上面添加创建对象注解
在注解里面 value 属性值可以省略不写, //默认值是类名称,首字母小写
3、开启组件扫描配置的细节
①use-default-filters="false" 表示现在不使用默认 filter,需要自己配置
filter context:include-filter ,设置扫描哪些内容
<context:component-scan base-package="com.haiyu.spring" use-default-filters="false">
<context:include-filter type="annotation"
expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
②下面配置扫描包所有内容
context:exclude-filter: 设置哪些内容不进行扫描
<context:component-scan base-package="com.haiyu.spring">
<context:exclude-filter type="annotation"
expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
4、实现属性注入
@Value 注入普通类型属性
@Value(value = "abc")
private String name;
@Autowired (属于javax包下)根据属性类型进行自动装配
@Service
public class UserService {
//定义 dao 类型属性
//不需要添加 set 方法
//添加注入属性注解
@Autowired
private UserDao userDao;
public void add() {
System.out.println("service add.......");
userDao.add();
}
}
@Qualifier (属于javax包下)根据名称进行自动装配,需要和@Autowired一起使用
@Autowired //根据类型进行注入
@Qualifier(value = "userDaoImpl1") //根据名称进行注入
private UserDao userDao;
@Resource(不是内部注解)既可以根据类型进行自动装配,也可以根据名称进行自动装配
//@Resource //根据类型进行注入
@Resource(name = "userDaoImpl1") //根据名称进行注入
private UserDao userDao;
bean生命周期:
(1)通过构造器创建 bean 实例(无参数构造)
(2)为 bean 的属性设置值和对其他 bean 引用(调用 set 方法)
(3)把 bean 实例传递 bean 后置处理器的方法 postProcessBeforeInitialization
(4)调用 bean 的初始化的方法(需要进行配置初始化的方法)
(5)把 bean 实例传递 bean 后置处理器的方法 postProcessAfterInitialization
(6)bean 可以使用了(对象获取到了)
(7)当容器关闭时候,调用 bean 的销毁的方法(需要进行配置销毁的方法)