Spring笔记上(基于XML配置)

news2024/11/15 19:57:54

在这里插入图片描述

新年快乐。

文章目录

  • 一、Spring概述
    • 1. 为什么要用Spring框架?
    • 2. Spring介绍
  • 二、IOC/DI快速入门
    • 1. IOC控制反转
    • 2. DI依赖注入
  • 三、Bean的配置
    • 1. Bean的基础配置
    • 2. Bean的别名配置
    • 3. Bean的作用范围配置
  • 四、Bean的实例化
    • 1. 构造方法方式
    • 2. 静态工厂方式
    • 3. 实例工厂方式
    • 4. 实现FactoryBean\<T>方式
  • 五、Bean的生命周期
    • 1. Bean的生命周期控制
      • 1.1 提供生命周期控制方法
      • 1.2 实现InitializingBean,DisposableBean接口
    • 2. bean的生命周期控制执行流程
    • 3. Bean的销毁时机
  • 六、依赖注入(DI配置)
    • 1.依赖的注入方式
      • 1.1 setter方式注入
        • 使用set方式注入引用类型(property-ref)
        • 使用set方式注入简单类型(property-value)
      • 1.2 构造方式注入
        • 使用构造方式注入引用类型( constructor-arg--ref)
        • 使用构造方式注入简单类型( constructor-arg--value)
        • 参数适配(扩展)
    • 2. 依赖自动装配
    • 3. 集合注入
      • 3.1 注入数组类型数据
      • 3.2 注入List类型数据
      • 3.3 注入Set类型数据
      • 3.4 注入Map类型数据
      • 3.5 注入Properties类型数据

在这里插入图片描述

一、Spring概述


1. 为什么要用Spring框架?


  • Spring 是一款轻量级、非侵入式的开源框架,企业用的人非常多,或者解耦合。
  • Spring可以简化开发,降低企业级开发的复杂度。(IOC控制反转、AOP面向切面编程)
  • Spring可以和许多优秀的框架整合(MyBatis、MP、Struts2、Hibernate、Junit、JPA等等)。

Spring框架应该怎么学:学Spring框架设计思想和基本使用。


2. Spring介绍


Spring官网:https://spring.io/

Spring文档地址:https://docs.spring.io/spring-framework/docs/5.2.10.RELEASE/spring-framework-reference/core.html#spring-core

在这里插入图片描述

Spring 是 JavaEE 领域的一款轻量级、非侵入式的开源框架,该框架由Rod Johnson于 2002 年提出并随后创建(最初版本是interface21)。其目的是为了简化Java企业级应用程序开发的复杂度(简单来讲是解耦合)。

Spring是一个开源容器框架,它集成各类型的工具,通过核心的BeanFactory实现了底层的类的实例化和生命周期的管理。在整个框架中,各类型的功能被抽象成一个个的 Bean,这样就可以实现各种功能的管理,包括动态加载和切面编程。


Spring两大特性:IOC控制反转、AOP面向切面编程。


IOC(Inversion of Control):控制反转。

  • IoC思想:把之前自己主动new对象的过程,转换成外部提供对象,然后对象创建控制权由自己转移到外部,这就是控制反转。
  • Spring提供了一个容器,称为IOC容器,用来充当IoC思想中的 ''外部"。
  • IOC容器负责对象的创建、初始化等,被创建或被管理的对象在IoC容器中统称为Bean。
  • 控制反转,就是把创建对象的权利交给 Spring管理,我们从Spring中获取对象使用即可。

DI(Dependency Injection):依赖注入,在IoC容器内将有依赖关系的bean进行关系绑定。(成员变量有两种注入方式:set、构造方法)


AOP:面向切面编程,AOP 用来封装多个类的公共行为,将那些与业务无关,却为业务模块所共同调用的逻辑封装起来,减少系统的重复代码,降低模块间的耦合度。另外,AOP 还解决一些系统层面上的问题,比如日志、事务处理、权限等。


Spring生态

在这里插入图片描述

  • Spring Framework(Spring Framework是Spring生态圈中最基础的项目,是其他项目的根基)。

  • Spring MVC( Web应用开发)。

  • SpringBoot(它为 Spring 以及第三方库提供一些开箱即用的配置,简化 Spring 应用的搭建及开发过程)。

  • SpringCloud(基于 Spring Boot 实现的微服务框架。它并不是某一门技术,而是一系列微服务解决方案或框架的有序集合。它将市面上成熟的、经过验证的微服务框架整合起来,并通过 Spring Boot 的思想进行再封装,屏蔽掉其中复杂的配置和实现原理,最终为开发人员提供了一套简单易懂、易部署和易维护的分布式系统开发工具包)。

  • Spring Data (数据访问模块,对JDBC和ORM提供了很好的支持。通过它,开发人员可以使用一种相对统一的方式,来访问位于不同类型数据库中的数据)。

  • Spring Security (前身 Acegi,是 Spring 中较成熟的子模块之一,它是一款可以定制化的身份验证和访问控制框架)。


Spring Framework系统架构图

Spring Framework是Spring生态圈中最基础的项目,是其他项目的根基。

在这里插入图片描述


二、IOC/DI快速入门


1. IOC控制反转


IOC:控制反转,将bean的创建权交给spring管理。

问题分析:

  • 哪些对象需要管理?(service与dao)

  • 如何将被管理的对象告知IOC容器?(配置文件或注解)

  • 被管理的对象交给IOC容器,如何获取到IoC容器?(使用Spring提供的API)

  • IOC容器得到后,如何从容器中获取bean?(使用Spring提供的API)

  • 使用Spring需要导入哪些依赖坐标?(spring-context)


IOC快速入门:

1、创建一个maven工程。

在这里插入图片描述

在这里插入图片描述


2、导入Spring依赖坐标。

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>5.2.10.RELEASE</version>
</dependency>

在这里插入图片描述

在这里插入图片描述


3、定义Spring管理的类(接口和实现类)

(1) 编写BookDao接口和BookDaoImpl实现类

package com.baidou.dao;
public interface BookDao {
    void save();
}
package com.baidou.dao;

public class BookDaoImpl implements BookDao {
    @Override
    public void save() {
        System.out.println("bookDao save~");
    }
}

在这里插入图片描述

(2) 编写BookService接口和BookServiceImpl实现类

package com.baidou.service;

public interface BookService {
    void save();
}
package com.baidou.service;

import com.baidou.dao.BookDao;
import com.baidou.dao.BookDaoImpl;

public class BookServiceImpl implements BookService {
	// 传统的依赖注入写法:直接在成员变量处创建对象、为成员变量提供set方法、通过构造器为成员变量初始化
    private BookDao bookDao = new BookDaoImpl(); 
    
    @Override
    public void save() {
        System.out.println("bookService save...");
        bookDao.save();
    }
}

在这里插入图片描述


4、创建spring配置文件,配置spring管理的bean对象。

在这里插入图片描述

定义applicationContext.xml配置文件,并对并BookServiceImpl进行配置。

<?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标签:用于配置bean对象的
            id属性:给bean起名字的(名字唯一)
            class属性:定义bean的类型
    -->
    <bean id="bookService" class="com.baidou.service.BookServiceImpl"></bean>

</beans>

在这里插入图片描述

注意事项:bean定义时,id属性在同一个spring配置文件(IOC容器中)不能重复出现。


5、初始化IOC容器(Spring容器),通过容器获取Bean对象。

package com.baidou;

import com.baidou.service.BookService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Application {
    public static void main(String[] args) {
        // 1.创建IoC容器对象,加载spring核心配置文件
        ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
        //System.out.println(ctx);//org.springframework.context.support.ClassPathXmlApplicationContext@1d56ce6a 表示ioc容器对象已经成功创建

        // 2. 从IOC容器中获取Bean对象  (例如我们配置的BookService对象)
        BookService bookService = (BookService) ctx.getBean("bookService"); // 通过id获取bean
                                         // 也可以通过name获取bean
        							  // 也可以通过类型获取bean: ctx.getBean(BookService.class)

        // 3.调用Bean对象(BookService对象)的方法
        bookService.save();
    }
}

在这里插入图片描述


2. DI依赖注入


DI:依赖注入,在spring容器中将bean的依赖关系绑定。(给bean设置成员变量)

DI使用分析:

  • 基于IoC管理bean。
  • service中需要使用dao对象,如何引入?(提供方法,set方法或者构造器)
  • 通过一些配置来描述service和dao之间的关系。

DI快速入门:

1、为成员变量提供setter方法

package com.baidou.service;

import com.baidou.dao.BookDao;
import com.baidou.dao.BookDaoImpl;

public class BookServiceImpl implements BookService {
	
    //   private BookDao bookDao=new BookDaoImpl();
    private BookDao bookDao;

    // 提供set方法
    public void setBookDao(BookDao bookDao) {
        this.bookDao = bookDao;
    }

    @Override
    public void save() {
        System.out.println("bookService save...");
        bookDao.save();
    }
}

在这里插入图片描述


2、在spring配置文件中,配置service与dao的依赖关系。

<?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">

    <!--bookService bean-->
    <bean id="bookService" class="com.baidou.service.BookServiceImpl">
        <!--
               property标签: 为bean设置属性
                    name属性: 指向bean的属性名(必须有set方法)
                    ref 属性: 指向bean容器中的那个对象 (此处写bean的名字即可)
        -->
        <!--将容器中名字为bookDao的bean设置给bookService中的bookDao属性-->
        <property name="bookDao" ref="bookDao"/>
    </bean>

    <!--bookDao bean-->
    <bean id="bookDao" class="com.baidou.dao.BookDaoImpl"></bean>

</beans>

注意:在spring中通过setter注入的属性的话,就必须为该属性提供对应的set方法。


3、测试

在这里插入图片描述


三、Bean的配置


1. Bean的基础配置


<bean id="bookService" class="com.baidou.service.BookServiceImpl"></bean>
<bean id="bookDao" class="com.baidou.dao.BookDaoImpl"></bean>
  • bean标签的作用:定义bean对象,让Sring容器管理。这个标签所属beans标签。
  • id属性:bean的id,在容器中通过id值获取对应的bean,在一个容器中id值是唯一的。
  • class属性:bean的类型,即配置bean的全路径类名。

2. Bean的别名配置


我们知道bean标签的id属性可以定义bean的名字,那么name属性就可以定义bean的别名

bean的别名可以定义多个,多个别名之间用 逗号(,)、分号(; ) 、空格分隔。

<bean id="bookService" name="service bookServiceImpl" class="com.baidou.service.BookServiceImpl"></bean>
<bean name="dao,bookDaoImpl" class="com.baidou.dao.BookDaoImpl"></bean>

注意:无论通过id还是name获取bean,如果容器中找不到bean,就会抛出异常:NoSuchBeanDefinitionException。(没有这样的bean)

在这里插入图片描述


示例:别名的使用

在这里插入图片描述

在这里插入图片描述


3. Bean的作用范围配置


通过bean标签的scope属性定义bean作用范围,常用的scope属性值有:

  • singleton:单例(ioc容器管理的对象默认是单例的,就不用配置scope属性)
  • prototype:非单例(需要配置scope属性,表示每次都能获取不同的对象,通过地址值判断)

扩展:scope的取值不仅仅只有singleton和prototype,还有request、session、global session等 ,表示创建出的对象放置在web容器(tomcat)对应的位置。比如:request表示保存到request域中。

示例:

在这里插入图片描述

在这里插入图片描述


小结

bean的配置:

  • scope:作用范围(单实例还是多实例) 默认单实例。

  • name:别名。(不常用)

  • init-method和destory-method:生命周期。(了解即可)


四、Bean的实例化


传统创建对象的方式:

  • new 类名() ; // 调用无参构造器。
  • 工厂类.方法(); // 调用某个类的静态方法
  • 某个对象.方法(); //调用某个对象的普通方法创建目标对象。例如 sqlSessionFactory.openSession();
  • 反射
  • 序列化

Bean的实例化方式有四种:构造方法方式、静态工厂方式、实例工厂方式、实现FactoryBean<T>方式(扩展)。

1. 构造方法方式


bean本质上就是对象,可以通过构造方法方式实例化bean。(重点)

1、为实现类BookDaoImpl提供一个构造方法

public class BookDaoImpl implements BookDao {

    // 显示定义一个无参构造方法
    public BookDaoImpl() {
        System.out.println("bookDao的构造方法执行了~");
    }

    @Override
    public void save() {
        System.out.println("bookDao save~");
    }
}

2、配置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 -->
	<bean id="bookDao" class="com.baidou.dao.BookDaoImpl"/>
</beans>

3、编写测试

public class Application {
    public static void main(String[] args) {
        // 创建IOC容器对象,并加载spring核心配置文件
        ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
        // 获取容器中的bean对象
        BookDao bookDao = (BookDao) ctx.getBean("bookDao");

        //  调用bean的方法
        bookDao.save();
    }
}

在这里插入图片描述


注意:如果定义了有参构造器方法,没有提供无参构造方法,就会抛出异常:BeanInstantiationException(bean实例化异常)

在这里插入图片描述

在这里插入图片描述


2. 静态工厂方式


通过示例静态工厂方式实例化bean。

1、定义接口和实现类

package com.baidou.dao;

public interface OrderDao {
    public void save();
}
package com.baidou.dao;

public class OrderDaoImpl implements OrderDao {
    
    public void save() {
        System.out.println("orderDao save ...");
    }
}

2、编写工厂类

package com.baidou.factory;

import com.baidou.dao.OrderDao;
import com.baidou.dao.OrderDaoImpl;

// 静态工厂创建对象
public class OrderDaoFactory {

    public static OrderDao getOrderDao() {
        return new OrderDaoImpl() ;
    }
}

3、在applicationContext.xml中,配置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 -->
  <bean id="orderDao" class="com.baidou.factory.OrderDaoFactory" factory-method="getOrderDao"/>
    
</beans>

在这里插入图片描述


4、编写测试

package com.baidou;

import com.baidou.dao.OrderDao;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Application {
    public static void main(String[] args) {
        // 创建IOC容器对象,并加载spring核心配置文件
        ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
        // 获取容器中的bean对象
        OrderDao orderDao = (OrderDao) ctx.getBean("orderDao");

        //  调用bean的方法
        orderDao.save();
    }
}

在这里插入图片描述


3. 实例工厂方式


通过实例工厂方式实例化bean。

1、定义接口和实现类

package com.baidou.dao;

public interface UserDao {
    public void save();
}
package com.baidou.dao;

public class UserDaoImpl implements UserDao {
    @Override
    public void save() {
        System.out.println("userDao save ...");
    }
}

2、编写工厂类

package com.baidou.factory;

import com.baidou.dao.UserDao;
import com.baidou.dao.UserDaoImpl;

//实例工厂创建对象
public class UserDaoFactory {
    public UserDao getUserDao(){
        return new UserDaoImpl();
    }
}

3、在applicationContext.xml中,配置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-->

    <!-- 配置实例工厂的bean-->
    <bean id="userFactory" class="com.baidou.factory.UserDaoFactory"/>
    <!--
        调用工厂对象的普通方法创建userDao对象
    -->
    <bean id="userDao"  factory-bean="userFactory" factory-method="getUserDao"></bean>

</beans>

在这里插入图片描述


4、编写测试

public class Application {
    public static void main(String[] args) {
        // //创建实例工厂对象
        // UserDaoFactory userDaoFactory = new UserDaoFactory();
        // //通过实例工厂对象创建对象
        // UserDao userDao = userDaoFactory.getUserDao();
        // userDao.save();
        ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
        UserDao userDao = (UserDao) ctx.getBean("userDao");
        userDao.save();
    }
}

在这里插入图片描述


4. 实现FactoryBean<T>方式


spring底层会用

1、定义UserDaoFactoryBean类,去实现FactoryBean<UserDao>接口。

  • UserDaoFactoryBean中实例化什么类型的对象,泛型就设置对应的类型。
//FactoryBean创建对象
public class UserDaoFactoryBean implements FactoryBean<UserDao> {
    // 重写接口中的两个方法
    
    //代替原始实例工厂中创建对象的方法
    public UserDao getObject() throws Exception {
        return new UserDaoImpl();
    }

    public Class<?> getObjectType() {
        return UserDao.class;
    }
}

2、配置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">	
    <!--方式四:使用FactoryBean实例化bean-->
    <!--
		factoryBean:
			创建对象的时候,spring会判断当前类有无实现factoryBean接口,
			若实现了,就会调用两个方法创建目标对象,且将对象放入spring容器管理		
	-->
    <bean id="userDao" class="com.baidou.factory.UserDaoFactoryBean"/>
<beans/>    

3、编写测试:

public class Application {
    public static void main(String[] args) {
        ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
        UserDao userDao = (UserDao) ctx.getBean("userDao");
        userDao.save();
    }
}

在这里插入图片描述


小结:

bean实例化方式:构造器方式(无参构造)。


五、Bean的生命周期


生命周期:就是从创建到消亡的完整过程。

bean生命周期:bean从创建到销毁的整体过程。

bean生命周期控制:bean从创建后到销毁前做一些事情。

1. Bean的生命周期控制


1.1 提供生命周期控制方法


1、提供声明周期方法(init和destory方法)

public class BookDaoImpl implements BookDao {
    public void save() {
        System.out.println("bookDao save ...");
    }
    //表示bean初始化对应的操作
    public void init(){
        System.out.println("init...");
    }
    //表示bean销毁前对应的操作
    public void destory(){
        System.out.println("destory...");
    }
}

2、在spring核心配置文件中,配置生命周期控制方法:

<?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">

    <!--init-method:设置bean初始化生命周期回调函数,此处填写init方法名-->
    <!--destroy-method:设置bean销毁生命周期回调函数,仅适用于单例对象,此处填写destory方法名-->
    <bean id="bookDao" class="com.baidou.dao.BookDaoImpl" init-method="init" destroy-method="destory"/>

</beans>

3、编写测试

public class App {
    public static void main(String[] args) {
        ClassPathXmlApplicationContext ctx =  new ClassPathXmlApplicationContext("applicationContext.xml");
       
        ctx.registerShutdownHook(); //优雅的关闭容器写法:先注册一下,当这些代码全部执行完毕后就销毁容器
        
        BookDao bookDao = (BookDao) ctx.getBean("bookDao");
        bookDao.save();
        
        // 若想执行destory销毁方法,需要关闭spring容器
        //ctx.close(); //缺点:close()方法必须放在最后一行执行
    }
}
/*
	当创建spring容器的时候,默认它会将配置文件中的所有单实例对象都创建好,且放入spring容器中;
	若配置init-method、destroy-method,就会去调用指定的方法。
*/

在这里插入图片描述

单实例的话,也可以在bean标签中配置lazy-init="true",表示用的时候创建bean。



多实例的话,用的时候才会去创建bean,bean的销毁由垃圾回收机制处理。

在这里插入图片描述


1.2 实现InitializingBean,DisposableBean接口


实现InitializingBean、DisposableBean接口,重写接口中的两个方法:destroy、afterPropertiesSet

package com.baidou.dao;

import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;

public class BookDaoImpl implements BookDao, InitializingBean, DisposableBean {

    public BookDaoImpl() {
        System.out.println("bookDao 无参构造方法执行了");
    }

    public void save() {
        System.out.println("bookDao save ...");
    }

    // 在bean对象销毁前要执行的方法
    @Override
    public void destroy() throws Exception {
        System.out.println("destroy ...");
    }

    // 在bean设置完属性之后会执行的方法 (相当于init-method配置)
    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("init ...");
    }
}
<?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="bookDao" class="com.baidou.dao.BookDaoImpl"></bean>

</beans>
public class App {
    public static void main(String[] args) {
        ClassPathXmlApplicationContext ctx =  new ClassPathXmlApplicationContext("applicationContext.xml");
        ctx.registerShutdownHook(); //优雅的关闭容器方式:先注册一下,当这些代码全部执行完毕后就销毁容器
        BookDao bookDao = (BookDao) ctx.getBean("bookDao");
        bookDao.save();
    }
}

在这里插入图片描述


2. bean的生命周期控制执行流程


1、初始化容器

2、创建对象(内存分配)

3、执行构造方法

4、执行属性注入(set操作)

5、执行bean初始化方法:

  • 若在bean中配置了init-method,就会执行指定的方法。
  • 若实现了InitializingBean接口的话就会执行afterPropertiesSet。

6、使用bean执行业务操作

7、关闭/销毁容器之前执行bean销毁方法:

  • 若实现了DisposableBean接口的话,就会执行destroy方法。
  • 若在bean中配置了destroy-method的话就会执行指定的方法。

3. Bean的销毁时机


IOC容器关闭前才会触发bean的销毁。

关闭容器的两种方式:

1、手动关闭容器:通过ConfigurableApplicationContext接口的close()方法。

2、注册关闭钩子,在虚拟机退出前先关闭容器再退出虚拟机:通过ConfigurableApplicationContext接口的registerShutdownHook()方法。


六、依赖注入(DI配置)


1.依赖的注入方式

依赖注入有两种方式:setter方式、构造器方式。

1.1 setter方式注入


setter方式:

  • 在类中提供给成员变量提供setter方法。
  • 在配置文件中通过 <property name=“属性名” ref|value=“”/>。
  • ref:注入引用类型。
  • value:注入简单类型。

使用set方式注入引用类型(property-ref)

package com.baidou.service;

import com.baidou.dao.BookDao;

public class BookServiceImpl implements BookService {

    private BookDao bookDao;

    // 为成员变量提供set方法
    public void setBookDao(BookDao bookDao) {
        this.bookDao = bookDao;
    }

    @Override
    public void save() {
        System.out.println("bookService save...");
    }
}
<!--bookService -->
<bean id="bookService" class="com.baidou.service.BookServiceImpl">
    <!--使用property标签的ref属性注入引用类型对象-->
    <property name="bookDao" ref="bookDao"></property>
</bean>

<!--bookDao-->
<bean class="com.baidou.dao.BookDaoImpl" id="bookDao"></bean>

在这里插入图片描述


使用set方式注入简单类型(property-value)

package com.baidou.dao;

public class BookDaoImpl implements BookDao {
    // 定义简单类型成员变量
    private int connectionNumber;

    // 提供set方法
    public void setConnectionNumber(int connectionNumber) {
        this.connectionNumber = connectionNumber;
    }

    public void save() {
        System.out.println("bookDao save ...");
    }
}
<bean class="com.baidou.dao.BookDaoImpl" id="bookDao">
    <!-- 使用property标签的value属性注入简单类型-->
    <property name="connectionNumber" value="10"/>
</bean>

在这里插入图片描述


1.2 构造方式注入


构造器方式:

  • 在类中提供给成员变量赋值的构造器。
  • 在配置文件中通过 <constructor-arg name=“参数名字” ref|value=“”/>。
  • ref:注入引用类型。
  • value:注入简单类型。

使用构造方式注入引用类型( constructor-arg–ref)

package com.baidou.service;

import com.baidou.dao.BookDao;

public class BookServiceImpl implements BookService {

    private BookDao bookDao;
    
    // 提供无参构造器
    public BookServiceImpl() {}

    //  通过带参构造器
    public BookServiceImpl(BookDao bookDao) {
        this.bookDao = bookDao;
    }

    @Override
    public void save() {
        System.out.println("bookService save...");
    }
}
<!--bookService -->
<bean id="bookService" class="com.baidou.service.BookServiceImpl">
    <!--通过constructor-arg标签的ref属性注入引用类型对象-->
    <constructor-arg name="bookDao" ref="bookDao"/>
</bean>

<!--bookDao-->
<bean class="com.baidou.dao.BookDaoImpl" id="bookDao"></bean>

在这里插入图片描述


使用构造方式注入简单类型( constructor-arg–value)

public class BookDaoImpl implements BookDao {
    // 定义简单类型成员变量
    private int connectionNumber;
    private String databaseName;

    // 提供无参构造器
    public BookDaoImpl() {}

    // 提供带参构造器
    public BookDaoImpl(int connectionNumber, String databaseName) {
        this.connectionNumber = connectionNumber;
        this.databaseName = databaseName;
    }

    public void save() {
        System.out.println("bookDao save ...");
    }
}
<bean class="com.baidou.dao.BookDaoImpl" id="bookDao">
    <!--通过constructor-arg标签的value属性注入简单类型数据-->
    <constructor-arg name="connectionNumber" value="10"/>
    <constructor-arg name="databaseName" value="redis"/>
</bean>

在这里插入图片描述


参数适配(扩展)

1、通过constructor-arg标签的type属性设置按照形参类型注入

在这里插入图片描述

<!--bookDao-->
<bean class="com.baidou.dao.BookDaoImpl" id="bookDao">
    <constructor-arg type="int" value="10"/>
    <constructor-arg type="java.lang.String" value="redis"/>
</bean>

2、通过constructor-arg标签的index属性设置按照形参位置注入

<!--bookDao-->
<bean class="com.baidou.dao.BookDaoImpl" id="bookDao">
    <constructor-arg index="0" value="10"/>
    <constructor-arg index="1" value="mysql"/>
</bean>

依赖注入方式选择:

  1. 强制依赖使用构造器进行,使用setter注入有概率导致null对象出现。
  2. 可选依赖使用setter注入进行,灵活性强。
  3. Spring框架倡导使用构造器,第三方框架内部大多数采用构造器注入的形式进行数据初始化,相对严谨。
  4. 如果有必要可以两者同时使用,使用构造器注入完成强制依赖的注入,使用setter注入完成可选依赖的注入。
  5. 实际开发过程中还要根据实际情况分析,如果受控对象没有提供setter方法就必须使用构造器注入。
  6. 自己开发的模块推荐使用setter注入

2. 依赖自动装配


IoC容器根据bean所依赖的资源在容器中自动查找并注入到bean中的过程称为自动装配。(后面会用@autowire注解实现)

自动装配方式有:

  • 按类型进行装配(常用)
  • 按名称进行装配
  • 按构造方法进行装配
  • 不启用自动装配

在配置文件中,通过bean标签的autowire属性设置自动装配的类型:(给成员变量提供setter方法)

<bean id="bookDao" class="com.baidou.dao.BookDaoImpl"/>
<bean id="bookService" class="com.baidou.service.BookServiceImpl" autowire="byType"/>

依赖自动装配特征:

  1. 自动装配用于引用类型依赖注入,不能对简单类型进行操作。
  2. 使用按类型装配时(byType)必须保障容器中相同类型的bean唯一,推荐使用。
  3. 使用按名称装配时(byName)必须保障容器中具有指定名称的bean,因变量名与配置耦合,不推荐使用。
  4. 自动装配优先级低于setter注入与构造器注入,同时出现时自动装配配置失效。

3. 集合注入


property标签通过setter方式注入,内部可以写<array>、<list>、<set>、<map>、<props>标签。

constructor-arg标签通过构造方式注入,constructor-arg标签内部也可以写<array>、<list>、<set>、<map>、<props>标签。

单列集合:array、set、list。

双列集合:map、props。

3.1 注入数组类型数据

<property name="array">
    <array>
        <value>1</value>
        <value>2</value>
        <value>3</value>
    </array>
</property>

3.2 注入List类型数据

<property name="list">
    <list>
        <value>java</value>
        <value>php</value>
        <value>python</value>
        <value>c++</value>
    </list>
</property>

3.3 注入Set类型数据

<property name="set">
    <set>
        <value>java</value>
        <value>php</value>
        <value>python</value>
        <value>java</value>
    </set>
</property>

3.4 注入Map类型数据

<property name="map">
    <map>
        <entry key="country" value="china"/>
        <entry key="province" value="zhejiang"/>
        <entry key="city" value="hangzhou"/>
    </map>
</property>

3.5 注入Properties类型数据

<property name="properties">
    <props>
        <prop key="country">china</prop>
        <prop key="province">zhejiang</prop>
        <prop key="city">hangzhou</prop>
    </props>
</property>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/176289.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Java面试题,JVM相关问题

JVM相关问题一 、JDK、JRE、JVM二、内存管理三、GC如何判断对象可以被回收&#xff08;这是JVM的基础&#xff09;一 、JDK、JRE、JVM JDK&#xff1a;Java Development Kit【Java开发工具】&#xff0c;提供给Java开发人员来使用的。JRE&#xff1a;Java Runtime Environment…

Solid Edge 放样使用引导曲线

放样用引导曲线的时候被一个错误提示卡了挺长时间——“选来用作路径或横截面的所有边必须连接在一起”&#xff0c;所以记录一下遇到的问题。基础的操作可以去看帮助文件https://docs.sw.siemens.com/zh-CN/doc/246738425/PL20211001099989437.feature_modeling/feat12c&#…

Sprig框架集成(SSM框架) | Sping+SpringMVC+Mybatis

SSM框架 SSM是spingspringMVCmybatis集成的框架&#xff1a;标准的MVC模式&#xff0c;整个系统划分为表现层&#xff0c;controller层&#xff0c;service层&#xff0c;DAO层四层 Spring&#xff08;业务层&#xff09; Spring就像是整个项目中装配bean的大工厂&#xff0c;在…

MySQL server options

介绍 MySQL安装部署时&#xff0c;经常会关注一些参数是否合理。其实这些参数分为两类型。环境中调整的绝大部分是引擎层方面的。服务层参数&#xff0c;就是mysqld服务启动时的参数&#xff0c;如&#xff1a;datadir&#xff0c;port&#xff0c;socket之类的的&#xff0c;…

多重背包问题——单调队列优化

一、多重背包问题 我们在之前的文章中曾经讲解过多重背包问题&#xff0c;当时我们讲解了两种方法&#xff0c;一种方法就是三重循环&#xff0c;这种方法最为朴素好想。但是这种方法的时间复杂度非常高&#xff0c;后来我们想到了二进制优化的方式。那么今天我们将再介绍一种…

Java实习------Java基础2

基础语法基本数据类型 熟悉Java有哪些数据类型定义&#xff1a;Java语言是强类型语言&#xff0c;对于每一种数据都定义了明确的具体的数据类型&#xff0c;在内存中分配了不同大小的内存空间。Java语言提供了八种基本类型。六种数字类型&#xff08;四个整数型&#xff0c;两个…

18. 循环语句while,for语句的详解

python 中的循环语句只有 for 和 while两种&#xff0c;没有do…while循环&#xff0c;这与c/c是不同的。 1. while循环 (1) 语法格式 while <condition>&#xff1a;...# demo, 使用while循环累加1-100的和。 sum 0 counter 1 while counter < 100:sum counterco…

Java 23种设计模式(4.创建者模式-建造者模式)

代码分析 结构图 代码 public class Product {//产品类,多个部件构成List <String> parts new ArrayList<>();public void Add(String part){parts.add(part);}public void show(){System.out.println("creat parts");for(String part:parts){System…

第十届蓝桥杯省赛 C++ B/C组 - 等差数列

✍个人博客&#xff1a;https://blog.csdn.net/Newin2020?spm1011.2415.3001.5343 &#x1f4da;专栏地址&#xff1a;蓝桥杯题解集合 &#x1f4dd;原题地址&#xff1a;等差数列 &#x1f4e3;专栏定位&#xff1a;为想参加蓝桥杯的小伙伴整理常考算法题解&#xff0c;祝大家…

STL分析(九 适配器)

容器适配器&#xff1a;stack&#xff0c;queue stack和queue内含一个deque 函数适配器 binder2nd绑定第二参数 调用的过程中&#xff0c;算法count_if函数读取了迭代器头尾指针后&#xff0c;读取第三个参数为functor object即仿函数。因此在其参数为bind2nd(less< int&g…

LeetCode220123_140、117. 填充每个节点的下一个右侧节点指针 II

给定一个二叉树struct Node {int val;Node *left;Node *right;Node *next;}填充它的每个 next 指针&#xff0c;让这个指针指向其下一个右侧节点。如果找不到下一个右侧节点&#xff0c;则将 next 指针设置为 NULL。初始状态下&#xff0c;所有 next 指针都被设置为 NULL。进阶…

双指针思想,c语言

问题导入 对一个给定的自然数M&#xff0c;求出所有的连续的自然数段&#xff0c;这些连续的自然数段中的全部数之和为M。 例如&#xff1a;1998 1999 2000 2001 2002 10000&#xff0c;所以从1998到2002的一个自然数段为M 10000的一个解。 输入格式 第一行&#xff0…

JQuery总结(三)

jQuery 事件 on可以同时绑定多个事件&#xff0c;并且动态添加的元素也会自动添加事件 自动触发事件&#xff1a; 案例1&#xff1a; <style>div{width: 100px;height: 200px;background-color: violet;transition: all .5s;}.current{width: 200px;height: 100px;ba…

ARP渗透与攻防(三)之流量分析

ARP攻击-流量分析 ARP渗透与攻防(一)之ARP原理 ARP渗透与攻防(二)之断网攻击 系列文章 1.环境准备 1.kali作为攻击机 2.win10作为靶机 IP地址&#xff1a;192.168.110.11 3.网关 IP地址&#xff1a;192.168.110.1 2.kali数据包转发 出于安全考虑&#xff0c;Linux系统默…

使用Py6S计算瑞利反射率教程

1、前言那么&#xff0c;首先&#xff0c;什么是瑞利反射率&#xff1f; 好吧&#xff0c;这是由大气中的瑞利散射引起的反射率&#xff08;在大气层顶部测量&#xff09;。 这是大气中气体分子对光的波长依赖性散射——这是光穿过大气时不可避免的结果。所以&#xff0c;关于如…

【2022年度总结与2023展望】---22年故事不长,且听我来讲

&#x1f680;write in front&#x1f680; &#x1f4dd;个人主页&#xff1a;认真写博客的夏目浅石. &#x1f4e3;系列专栏&#xff1a;故事 文章目录前言一、高考前及高考后的暑假二、大一上的生活2.1 感受校园美景2.2 进入ACM实验室2.3 比赛和比赛经历三、那些帮助过我的人…

AlmaLinux 9 安装Oracle GraalVM Enterprise Edition 22.3.x

今天我们尝试一下在AlmaLinux 9 安装Oracle GraalVM Enterprise Edition 22.3.x。 GraalVM Enterprise 22是包含新功能的最新版本&#xff0c;但不是Long-Term-Support (LTS) 版本。 注意&#xff1a;下载Oracle GraalVM Enterprise Edition需要有Oracle账户&#xff0c;如果没…

六、pyhon操作mysql篇(黑马程序猿-python学习记录)

黑马程序猿的python学习视频&#xff1a;https://www.bilibili.com/video/BV1qW4y1a7fU/ 目录 1. 下载pymysql 2. 新建数据库 3. mysql服务器版本查询 4. 执行非查询性质的SQL 5. 执行查询性质的sql ​​​​​​​6. 执行新增sql 1. 下载pymysql 右下角点击版本 选择解释器设…

基于Markdown文件的个人wiki

节后第一更&#xff0c;老苏祝您兔年大吉&#xff0c;幸福安康&#xff0c;事事顺心&#xff01; 什么是 wikmd &#xff1f; wikmd 是一个基于文件的 wiki&#xff0c;旨在简化。这些文档完全用 Markdown 编写&#xff0c;使用 pandoc 将 Markdown 文件转换为 html5。 &#…

WPF__Viewport3D 学习记录

1、相机的摆放位置和姿态 Position 是指定照相机的位置&#xff0c;注意Z轴的坐标&#xff0c;如果Z轴值大于模型的Z轴值&#xff0c;那么镜头就在物体前面&#xff0c;反之在物体后面。因此&#xff0c;你可以设置 LookDirection 来调整相机的方向&#xff0c;Position是相机的…