1.BeanFactory和ApplicationContext的区别:

BeanFactory是Spring框架中IOC容器的顶层接口,它只是用来定义一些基础功能,定义一些基础规范,而ApplicationContext是它的一个子接口,所以ApplicationContext是具备BeanFactory提供的全部功能。

通常我们称BeanFactory为SpringIOC的基础容器,ApplicationContext是容器的高级接口,比如BeanFactory拥有更多的功能,比如说国际化支持和资源访问(xml、java配置类)等等。

2.实例化bean的三种方式:

⽅式⼀:使⽤⽆参构造函数

在默认情况下,它会通过反射调⽤⽆参构造函数来创建对象。如果类中没有⽆参构造函数,将创建失败。

<bean id="connectionUtils" class="com.lagou.edu.utils.ConnectionUtils"></bean>

⽅式⼆:使⽤静态⽅法创建

在实际开发中,我们使⽤的对象有些时候并不是直接通过构造函数就可以创建出来的,它可能在创建的过程中会做很多额外的操作。此时会提供⼀个创建对象的⽅法,恰好这个⽅法是static修饰的⽅法,即是此种情况。

例如,我们在做Jdbc操作时,会⽤到java.sql.Connection接⼝的实现类,如果是mysql数据库,那么⽤的就是JDBC4Connection,但是我们不会去写 JDBC4Connection connection = newJDBC4Connection() ,因为我们要注册驱动,还要提供URL和凭证信息,⽤ DriverManager.getConnection ⽅法来获取连接。

那么在实际开发中,尤其早期的项⽬没有使⽤Spring框架来管理对象的创建,但是在设计时使⽤了⼯⼚模式解耦,那么当接⼊spring之后,⼯⼚类创建对象就具有和上述例⼦相同特征,即可采⽤此种⽅式配置。

<!--使⽤静态⽅法创建对象的配置⽅式-->
<bean id="userService" class="com.lagou.factory.BeanFactory"
factory-method="getTransferService"></bean>

⽅式三:使⽤实例化⽅法创建

此种⽅式和上⾯静态⽅法创建其实类似,区别是⽤于获取对象的⽅法不再是static修饰的了,⽽是类中的⼀ 个普通⽅法。此种⽅式⽐静态⽅法创建的使⽤⼏率要⾼⼀些。

在早期开发的项⽬中,⼯⼚类中的⽅法有可能是静态的,也有可能是⾮静态⽅法,当是⾮静态⽅法时,即可采⽤下⾯的配置⽅式:

<!--使⽤实例⽅法创建对象的配置⽅式-->
<bean id="beanFactory"
class="com.lagou.factory.instancemethod.BeanFactory"></bean> <bean id="transferService" factory-bean="beanFactory" factory-method="getTransferService"></bean>

3.Bean的作用范围和生命周期

3.1作用范围——scope

经常使用的有singletonprototype

    <!-- scope: 定义bean的作用范围
singleton(默认)单例:IOC容器只有一个该类对象
prototype 原型:每次使用该类的对象(getBean),都返回一个新的对象
-->
<bean id="accountDao" class="com.lagou.edu.dao.impl.JdbcAccountDaoImpl" >
<property name="ConnectionUtils" ref="connectionUtils"></property>
</bean>

测试:

   <bean id="accountDao" class="com.lagou.edu.dao.impl.JdbcAccountDaoImpl" >
<property name="ConnectionUtils" ref="connectionUtils"></property>
</bean>
//===
@org.junit.Test
public void test(){
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
AccountDao accountDao = (AccountDao) applicationContext.getBean("accountDao");
System.out.println("accountDao:"+accountDao);
AccountDao accountDao1 = (AccountDao) applicationContext.getBean("accountDao");
System.out.println("accountDao1:"+accountDao1);
}
//得出结果为:
accountDao:com.lagou.edu.dao.impl.JdbcAccountDaoImpl@58cbafc2
accountDao1:com.lagou.edu.dao.impl.JdbcAccountDaoImpl@58cbafc2
//同一个对象
   <bean id="accountDao" class="com.lagou.edu.dao.impl.JdbcAccountDaoImpl" scope="prototype">
<property name="ConnectionUtils" ref="connectionUtils"></property>
</bean>
//===
@org.junit.Test
public void test(){
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
AccountDao accountDao = (AccountDao) applicationContext.getBean("accountDao");
System.out.println("accountDao:"+accountDao);
AccountDao accountDao1 = (AccountDao) applicationContext.getBean("accountDao");
System.out.println("accountDao1:"+accountDao1);
}
//得出结果为:
accountDao:com.lagou.edu.dao.impl.JdbcAccountDaoImpl@75d3a5e0
accountDao1:com.lagou.edu.dao.impl.JdbcAccountDaoImpl@74d1dc36
//不是同一个对象

3.2生命周期

  • singleton(默认)单例:IOC容器只有一个该类对象

    • 对象出生:当容器创建时,对象就被创建了
    • 对象活着:只要容器在,对象就一直活着
    • 对象死亡:当容器销毁时,对象就被销毁了

    一句话总结:单例模式的bean对象生命周期与容器相同

  • prototype (多例)原型:每次使用该类的对象(getBean),都返回一个新的对象

    • 对象出生:当使用对象时创建新的对象实例
    • 对象活着:只要对象在使用中,就一直活着
    • 对象死亡:当对象长时间不用时,被java的垃圾回收器回收了

    一句话总结:多例模式的bean对象,spring框架只负责创建,不负责销毁

init-method属性:⽤于指定bean对象的初始化⽅法,此⽅法会在bean对象装配后调⽤。必须是⼀个⽆参⽅法。

destory-method属性:⽤于指定bean对象的销毁⽅法,此⽅法会在bean对象销毁前执⾏它只能为scope是singleton时起作⽤。

4.DI依赖注入的xml配置

4.1 set方法注入

set注入使用property标签,如果注入的是另外一个bean使用ref属性,如果注入的是普通值使用value属性

   <bean id="accountDao" class="com.lagou.edu.dao.impl.JdbcAccountDaoImpl" scope="prototype" >
<property name="name" value="zhangsan"></property>
<property name="age" value="1"></property>
</bean>

4.2 构造函数注入

  • 根据有参构造函数参数索引

       <bean id="accountDao" class="com.lagou.edu.dao.impl.JdbcAccountDaoImpl" scope="prototype" >
    <constructor-arg index="0" ref="connectionUtils"></constructor-arg>
    <constructor-arg index="1" value="zhangsan"></constructor-arg>
    <constructor-arg index="2" value="1"></constructor-arg>
    </bean>
  • 根据有参构造函数参数名称:

       <bean id="accountDao" class="com.lagou.edu.dao.impl.JdbcAccountDaoImpl" scope="prototype" >
    <constructor-arg name="connectionUtils" ref="connectionUtils"></constructor-arg>
    <constructor-arg name="name" value="zhangsan"></constructor-arg>
    <constructor-arg name="age" value="1"></constructor-arg>
    </bean>

4.3 复杂类型

   <bean id="accountDao" class="com.lagou.edu.dao.impl.JdbcAccountDaoImpl" scope="prototype" >
<property name="ConnectionUtils" ref="connectionUtils"></property>
<!--注入复杂数据类型 -->
<!-- private String[] myArray;-->
<!-- private Map<String,String> myMap;-->
<!-- private Set<String> myset;-->
<!-- private Properties myProperties;-->
<property name="myArray">
<array>
<!-- 基本数据类型 就用value 引用类型就用 ref-->
<value>array1</value>
<value>array2</value>
</array>
</property> <property name="myMap">
<map>
<entry key="key1" value="value1" />
<entry key="key2" value="value2"/>
</map>
</property> <property name="mySet">
<set>
<value>set1</value>
<value>set2</value>
</set>
</property> <property name="myProperties">
<props>
<prop key="prop1">value1</prop>
<prop key="prop2">value2</prop>
</props>
</property>
</bean>

5.DI依赖注入的注解和xml相结合实现方式

哪些bean定义在xml中,哪些bean的定义使用注解?

第三方jar中的bean定义在xml

自己开发的bean使用注解

我是用Druid连接池,那么它属于第三方jar,所以我就在配置文件中配置

    <!-- 第三方jar中的bean定义在jar包中-->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
<property name="url" value="xxxx"></property>
<property name="username" value="xxxx"></property>
<property name="password" value="xxxx"></property>
</bean>

然后在使用它的地方使用注解:

5.1 @Autowired——按照类型注入

按照类型注入:如下带代码,它会在容器中找到一个类型为AccoutDao的对象注入进来

@Service("transferService")//不指定也可以,变成了类名的首字母小写
public class TransferServiceImpl implements TransferService {
//@Autowired 按照类型注入
@Autowired
private AccountDao accountDao;
//可以加在属性和set方法上,如果加在属性上,set方法就不需要了
// public void setAccountDao(AccountDao accountDao) {
// this.accountDao = accountDao;
// }

如果AccountDao有多个实现类 ,且多个实现类都配置在了IOC容器中,怎么办?

5.2 @Qualifier("具体id")——指定具体的id

@Service("transferService")
public class TransferServiceImpl implements TransferService {
//@Autowired 按照类型注入,如果按照类型无法唯一锁定对象,可以结合@Qualifier("具体的id")
@Autowired
@Qualifier("accountDao")
private AccountDao accountDao;

5.3 @Resource

@Resource 注解由J2EE 提供,需要导⼊包 javax.annotation.Resource。 (JDK11默认移除,jdk8可以直接使用)

@Resource 默认按照 ByName ⾃动注⼊。

public class TransferService {
@Resource
private AccountDao accountDao;
@Resource(name="studentDao")
private StudentDao studentDao;
@Resource(type="TeacherDao")
private TeacherDao teacherDao;
@Resource(name="manDao",type="ManDao")
private ManDao manDao;
}

如果同时指定了 nametype,则从Spring上下⽂中找到唯⼀匹配的bean进⾏装配,找不到则抛出异常。

如果指定了 name,则从上下⽂中查找名称(id)匹配的bean进⾏装配,找不到则抛出异常。

如果指定了 type,则从上下⽂中找到类似匹配的唯⼀bean进⾏装配,找不到或是找到多个,都会抛出异常。

如果既没有指定name,⼜没有指定type,则⾃动按照byName⽅式进⾏装配;

注意:

@Resource 在 Jdk 11中已经移除,如果要使⽤,需要单独引⼊jar包

<dependency>
<groupId>javax.annotation</groupId>
<artifactId>javax.annotation-api</artifactId>
<version>1.3.2</version>
</dependency>

5.4 注解扫描

5.4.1 引入命名空间——context
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
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
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd
">
5.4.2 开启注解扫描
<!--开启注解扫描,base-package指定扫描的包路径-->
<context:component-scan base-package="com.lagou.edu"></context:component-scan>

6.其他

引入外部资源文件:

<!--引入外部资源文件-->
<context:property-placeholder location="classpath:jdbc.properties" />

最终的配置文件只留下了一个第三方jar

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
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
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd
">
<!--开启注解扫描,base-package指定扫描的包路径-->
<context:component-scan base-package="com.lagou.edu"></context:component-scan>
<!--引入外部资源文件-->
<context:property-placeholder location="classpath:jdbc.properties" />
<!-- 第三方jar中的bean定义在jar包中-->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="${jdbc.driver}"></property>
<property name="url" value="${jdbc.url}"></property>
<property name="username" value="${jdbc.username}"></property>
<property name="password" value="${jdbc.password}"></property>
</bean>
</beans>

6.DI依赖注入,纯注解模式

不要xml配置文件,从java配置类启动

  1. 新建SpringCofig类
  2. 使用注解@Configuration 标识当前类是一个配置类
  3. 使用注解@ComponentScan({"com.lagou.edu"}) 代替<context:component-scan base-package="com.lagou.edu"></context:component-scan>进行注解扫描
  4. 使用注解@PropertySource({"classpath:jdbc.properties"}) 代替<context:property-placeholder location="classpath:jdbc.properties" />引入外部资源文件
  5. 使用@Bean 将⽅法返回对象加⼊SpringIOC 容器
  6. @Value 对变量赋值,可以直接赋值,也可以使⽤ ${} 读取资源配置⽂件中的信息
  7. 还可以使用@Import 引⼊其他配置类
//@Configuration 标识当前类是一个配置类
@Configuration
@ComponentScan({"com.lagou.edu"})
@PropertySource({"classpath:jdbc.properties"})
public class SpringConfig {
@Value("${jdbc.driver}")
private String driverClassName;
@Value("${jdbc.url}")
private String url;
@Value("${jdbc.username}")
private String username;
@Value("${jdbc.password}")
private String password; @Bean("dataSource")
public DataSource creatDataSource(){
DruidDataSource druidDataSource = new DruidDataSource();
druidDataSource.setDriverClassName(driverClassName);
druidDataSource.setUrl(url);
druidDataSource.setUsername(username);
druidDataSource.setPassword(password);
return druidDataSource;
}
}

6.1启动

6.1.1 JavaSE:
    @org.junit.Test
public void test(){
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(SpringConfig.class);
AccountDao accountDao = (AccountDao) applicationContext.getBean("accountDao");
System.out.println(accountDao);
}
6.1.2 JavaWeb:
  1. 配置web.xml文件

    <!DOCTYPE web-app PUBLIC
    "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
    "http://java.sun.com/dtd/web-app_2_3.dtd" > <web-app>
    <display-name>Archetype Created Web Application</display-name> <!--告诉ContextLoaderListener 使用注解的方式启动IOC容器-->
    <context-param>
    <param-name>contextClass</param-name>
    <param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value>
    </context-param> <!-- 配置启动类的全限定类名-->
    <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>com.lagou.edu.SpringConfig</param-value>
    </context-param> <!-- 使用监听器启动Spring的IOC容器-->
    <listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    </web-app>

SpringIOC基础知识总结的更多相关文章

  1. java基础知识精华

    转载:https://www.jianshu.com/p/6c078abb720f java基础知识 java内存模型 java运行时数据区域 hashMap 如何解决冲突 存储方式 冲突达到一定数量 ...

  2. .NET面试题系列[1] - .NET框架基础知识(1)

    很明显,CLS是CTS的一个子集,而且是最小的子集. - 张子阳 .NET框架基础知识(1) 参考资料: http://www.tracefact.net/CLR-and-Framework/DotN ...

  3. RabbitMQ基础知识

    RabbitMQ基础知识 一.背景 RabbitMQ是一个由erlang开发的AMQP(Advanced Message Queue )的开源实现.AMQP 的出现其实也是应了广大人民群众的需求,虽然 ...

  4. Java基础知识(壹)

    写在前面的话 这篇博客,是很早之前自己的学习Java基础知识的,所记录的内容,仅仅是当时学习的一个总结随笔.现在分享出来,希望能帮助大家,如有不足的,希望大家支出. 后续会继续分享基础知识手记.希望能 ...

  5. selenium自动化基础知识

    什么是自动化测试? 自动化测试分为:功能自动化和性能自动化 功能自动化即使用计算机通过编码的方式来替代手工测试,完成一些重复性比较高的测试,解放测试人员的测试压力.同时,如果系统有不份模块更改后,只要 ...

  6. [SQL] SQL 基础知识梳理(一)- 数据库与 SQL

    SQL 基础知识梳理(一)- 数据库与 SQL [博主]反骨仔 [原文地址]http://www.cnblogs.com/liqingwen/p/5902856.html 目录 What's 数据库 ...

  7. [SQL] SQL 基础知识梳理(二) - 查询基础

    SQL 基础知识梳理(二) - 查询基础 [博主]反骨仔 [原文]http://www.cnblogs.com/liqingwen/p/5904824.html 序 这是<SQL 基础知识梳理( ...

  8. [SQL] SQL 基础知识梳理(三) - 聚合和排序

    SQL 基础知识梳理(三) - 聚合和排序 [博主]反骨仔 [原文]http://www.cnblogs.com/liqingwen/p/5926689.html 序 这是<SQL 基础知识梳理 ...

  9. [SQL] SQL 基础知识梳理(四) - 数据更新

    SQL 基础知识梳理(四) - 数据更新 [博主]反骨仔 [原文]http://www.cnblogs.com/liqingwen/p/5929786.html 序 这是<SQL 基础知识梳理( ...

随机推荐

  1. scrapy Request方法

    # -*- coding: utf-8 -*- import scrapy class TestSpider(scrapy.Spider): name = 'test' allowed_domains ...

  2. selenium-窗口切换

    方法一 # 获取打开的多个窗口句柄 windows = driver.window_handles # 切换到当前最新打开的窗口 driver.switch_to.window(windows[-1] ...

  3. 用 Span 对 C# 进程中三大内存区域进行统一访问 ,太厉害了!

    一:背景 1. 讲故事 前段时间写了几篇 C# 漫文,评论留言中有很多朋友多次提到 Span,周末抽空看了下,确实是一个非常

  4. Hive Sql的窗口函数

    date: 2019-08-30 11:02:37 updated: 2019-08-30 14:40:00 Hive Sql的窗口函数 1. count.sum.avg.max.min 以 sum ...

  5. 栈&队列&并查集&哈希表(julyedu网课整理)

    date: 2018-11-25 08:31:30 updated: 2018-11-25 08:31:30 栈&队列&并查集&哈希表(julyedu网课整理) 栈和队列 1. ...

  6. Java 内存级默认DNS缓存

    Java 默认的DNS缓存时间,即不设置任一系统属性,如networkaddress.cache.ttl 设置SecurityManager 默认的CachePolicy为Forever,即永久缓存D ...

  7. STM32入门系列-STM32时钟系统,时钟初始化配置函数

    在前面推文的介绍中,我们知道STM32系统复位后首先进入SystemInit函数进行时钟的设置,然后进入主函数main.那么我们就来看下SystemInit()函数到底做了哪些操作,首先打开我们前面使 ...

  8. 学习写简单的RPC框架demo

    学习实现一个简单的RPC框架. 工程主要目录分级结构: rpc-common: 公共基础包,能力提供包 rpc-provider: 服务提供者 rpc-consumer:服务消费者 rpc-servi ...

  9. 【开源】使用.Net Core和GitHub Actions实现哔哩哔哩每日自动签到、投币、领取奖励

    BiliBiliTool是一个B站自动执行任务的工具,使用.NET Core编写,通过它可以实现B站帐号的每日自动观看.分享.投币视频,获取经验,每月自动领取会员权益.自动为自己充电等功能,帮助我们轻 ...

  10. Linux__用户用户组和权限

    用户用户组和权限 useradd +用户名, 添加这个用户 userdel +用户名, 删除这个用户(有残留 ) userdel -r +用户名, 彻底删除这个用户 groupadd +组名 ,添加这 ...