Spirng5 | IOC基础

1.Spring概述

  1. 轻量级开源的JavaEE框架
  2. Spring的两大核心IOC,AOP
  3. IOC控制反转,把创建对象的过程交给Spring管理
  4. Aop面向切面,在不修改源代码的基础上增加功能
  5. 使用Spring降低代码的耦合度,简化开发

2.IOP概述

  • 控制反转,创建对象及其调用的过程都交给Spring去实现
  • 常见的两种实现方式为xml解析或注解开发

2.1底层原理

  • IOC思想基于IOC容器,IOC容器的底层就是对象工厂
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    //1.xml配置文件,配置创建的对象
    <bean id="flag" class="com.User"></bean>
    //2.创建工厂类
    public static User getUser(){
    //2.1 xml解析
    String classValue = class属性值;
    //2.2 反射创建对象返回
    Class<?> aClass = Class.forName(classValue);
    return (User) aClass.newInstance();
    }

2.2加载配置接口

  • ApplicationContext:BeanFactory的子接口,提供更丰富的功能,饿汉式
  • BeanFactory:Spring内部使用接口,加载配置文件不会创建对象,获取对象时才创建 懒汉式
    1
    2
    3
    4
    5
    6
    //两个接口的主要实现类
    new FileSystemXmlApplicationContext();
    new ClassPathXmlApplicationContext();
    ApplicationContext acs = new ClassPathXmlApplicationContext("xml文件");
    //获取配置创建的对象
    User user = acs.getBean("xml中配置的id值", User.class);

3.Bean管理

  • Spring创建对象和spring注入属性构成bean管理
  • 两种管理方式:基于xml配置文件实现,基于注解方式实现

3.1xml注入格式

使用set注入

1
2
3
4
<!--entity类中属性需提供set方法-->
<bean id="类标识" class="类路径">
<property name="属性名称" value="注入属性值"/>
</bean>

有参构造注入

1
2
3
<bean id="类标识" class="类路径">
<constructor-arg name="属性名称" value="注入属性值"/>
</bean>

通过P标签注入

1
2
3
4
5
6
7
8
9
10
11
12
<!--在头文件里引入p标签-->
<beans xmlns:p="http://www.springframework.org/schema/p"/>
<bean id="order" class="Orders" p:属性名称="注入属性值">
<!--属性注入null值-->
<property name="orderName">
<null/>
</property>
<!--注入含有特殊符号的值:固定写法<![CDATA[这里写值]]>-->
<property name="orderAddress">
<value><![CDATA[<南京>]]></value>
</property>
</bean>

3.2外部Bean

1
2
3
4
5
6
7
<bean id="类标识" class="类路径">
<!--注入userDao对象
name属性:类里面属性名称
ref属性:userDao对象bean标签id值-->
<property name="userDao" ref="userDaoImpl"/>
</bean>
<bean id="userDaoImpl" class="com.dao.UserDaoImpl"/>

3.3内部Bean

1
2
3
4
5
6
7
8
9
<bean id="employee" class="com.ltd.Staff">
<property name="name" value="小明"/>
<!--在当前对象内部引入另外一个对象的属性-->
<property name="dept">
<bean class="com.ltd.Department">
<property name="dname" value="人事部"/>
</bean>
</property>
</bean>

级联赋值

1
2
3
4
5
6
7
8
9
10
<bean id="employee2" class="com.ltd.Staff">
<property name="name" value="汤姆"/>
<!--通过ref引入外部bean直接进行赋值-->
<property name="dept" ref="dept"/>
<!--优先使用内部标签-->
<property name="dept.dname" value="技术部"/>
</bean>
<bean id="dept" class="com.ltd.Department">
<property name="dname" value="研发部"/>
</bean>

3.4注入属性集合

集合与数组类型注入

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<!--数组与集合参数注入格式-->
<property name="类中属性名称">
<数组用array 集合用list或set>
<value>属性值</value>
</array|list|set>
</property>

<!--Map集合书写格式-->
<property name="map">
<map>
<entry key="Subject" value="java"></entry>
<entry key="爬虫" value="Python"></entry>
</map>
</property>

引用数据类型注入

1
2
3
4
5
6
7
8
9
<property name="courseList">
<list>
<!--通过ref标签引入course对象 可多个-->
<ref bean="fen1"/>
</list>
</property>
<bean id="fen1" class="collection.Course">
<property name="course_Name" value="线性代数"/>
</bean>

提取集合注入

1
2
3
4
<!--名称空间为util xmlns和xsi下都需要添加-->
<bean xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util.xsd"/>
1
2
3
4
5
6
7
8
9
10
11
<!--1.提取集合注入部分-->
<!--需要在配置中引入名称空间-->
<util:list id="bookList">
<value>国富论</value>
<value>挪威的森林</value>
</util:list>

<!--2.提取list集合类型属性注入使用-->
<bean id="book" class="collection.Course">
<property name="list" ref="bookList"/>
</bean>

4.作用域

  • 默认bean创建为单例模式
  • 若需设置为多实例模式只需在bean标签中,添加scope属性
    1
    <bean id="略" class="略" scope="填4.1中的四种值">

4.1Scope值

  1. singleton,单例,表示通过Spring容器获取的对象是唯一的,是默认值
  2. prototype,原型,表示通过Spring容器获取的对象是不同的
  3. request,请求,表示在异常HTTP请求内有效
  4. session,会话,表示在一个用户会话内有效

4.2使用场景

  • request和session一般用于web项目
  • singleton模式下,只要加载IOC容器,不管是否从IOC种取出bean,配置文件中的bean都会被创建,而且只会创建一个对象
  • prototype模式下,如果不从IOC中取出bean,则不创建对象,取一次bean,就会创建一个对象

5.外部属性文件

  1. 以数据库线程池druid为例
  2. 首先配置名称空间context
  3. 通过名称空间获取配置文件
    1
    2
    <context:property-placeholder location="配置文件"/>
    <!--bean文件中的propertiy的value格式为${配置文件中属性名称}-->

5.1properties文件

1
2
3
4
druid.driverClassName=com.mysql.jdbc.Driver
druid.url=jdbc:mysql://localhost:3306/bank
druid.username=root
druid.password=123456

5.2xml配置文件

1
2
3
4
5
6
7
<context:property-placeholder location="properties文件"/>
<bean id="druidII" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="${druid.driverClassName}"/>
<property name="url" value="${druid.url}"/>
<property name="username" value="${druid.username}"/>
<property name="password" value="${druid.password}"/>
</bean>

6.生命周期

  1. 通过构造器创建bean实例
  2. 为bean的属性设置值和对其他bean引入(设置set方法)
  3. 把bean实例传给bean后置处理器的方法postProcessBeforeInitalization
  4. 调用bean的初始方法
  5. 把bean实例传给bean后置处理器的方法postProcessAfterInitalization
  6. 对象获取到,bean可以使用
  7. 容器关闭时,调用bean的销毁方法(销毁方法需进行配置)

6.1后置处理器

  1. 让一个类实现BeanPostProcessor接口,重写里面的方法就得到了一个后置处理器
  2. postProcessBeforeInitalization方法在初始化前执行
  3. postProcessAfterInitalization方法在初始化后执行

7.注解注入

  • Spring针对bean管理中创建对象提供注解
  • 四个注解功能一样,都可以用来创建bean实例
  • @Component @Service
  • @Controller @Repository

7.1对象注入

  1. beans标签中引用名称空间context
  2. 开启组件扫描,可以使用上级目录,或用逗号隔开
    1
    <context:component-scanbase-package="com"/>
  3. 在需要创建对象的类上面添加四种注解任意一种
  4. 注解中value值可不写默认为类名(首字母会小写)
  5. 使用junit测试使用可以运行成功
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<!--两者等价--> 
@Repository(value = "helloSpring")
<bean id="helloSpring" class="com.class1.HelloSpring"/>

<!--了解内容-->
<!--设置组件扫面仅包含指定注解 自己配置filter-->
<context:component-scan base-package="com" use-default-filters="false">
<context:include-filter type="annotation"
expression="org.springframework.stereotype.Controller"/>
</context:component-scan>

<!--设置组件扫面不扫描包含指定注解-->
<context:component-scan base-package="com">
<context:exclude-filter type="annotation"
expression="org.springframework.stereotype.Repository"/>
</context:component-scan>

7.2属性注入

  • @Autowired 根据属性类型进行自动装配
  • @Qualifier 根据属性名称进行注入
  • @Resource 两者皆可注入
  • 注:@Resource和以上两者不同在于它为javax包下,若不存在需手动导入包或maven依赖

entity实现类及其接口

1
2
3
4
5
6
7
8
//接口
public interface UserDao {void show();}
//接口实现类1
@Component(value = "student")
public class StudentImpl implements UserDao;
//接口实现类2
@Component(value = "userDaoImpl1")
public class UserDaoImpl implements UserDao;

属性注入使用

1
2
3
4
5
6
7
8
9
//根据类型注入使用注解无需使用set方法
//Qualifier需搭配Autowired使用 一个接口存在多个实现类用于指定具体实现类
@Autowired
@Qualifier(value = "userDaoImpl1")
private UserDao userDao;

//相当于autowired和qualifier结合 指定name情况下根据属性名称 不指定情况下根据类型
@Resource(name = "student")
private UserDao student;

普通属性注入

1
2
@Value("窗前明月光,疑是地上霜")       
private String line_chinese;

7.3完全注解开发

通过创建一个java类添加注解文件来实现替代掉XML文件

基于xml开发

1
2
3
<bean id="helloSpring" class="类路径"/>
ApplicationContext acs =
new ClassPathXmlApplicationContext("xxx.xml");

完全基于注解开发效果同上

1
2
3
4
5
6
@Configuration
@ComponentScan(basePackages = {"指定包路径"})
public class SpringConfig {}

AnnotationConfigApplicationContext context =
new AnnotationConfigApplicationContext(SpringConfig.class);

Spirng5 | IOC基础
http://example.com/2022/07/21/Spring5/IOC基础/
Author
John Doe
Posted on
July 21, 2022
Licensed under