Spring的IOC和DI入门

时间:2022-08-28 01:09:06

1、相关概念

1.1、Spring来源

官网:Spring | Home

Spring是一个分层的Java SE/EE应用一站式的轻量级开源框架。Spring核心是IOCAOP
Spring主要优点包括:

  • 方便解耦,简化开发,通过Spring提供的IoC容器,我们可以将对象之间的依赖关系交由Spring进行控制,避免硬编码造成的程序耦合度高。
  • AOP编程的支持,通过Spring提供的AOP功能,方便进行面向切面编程。
  • 声明式事务的支持,在Spring中,我们可以从单调烦闷的事务管理代码中解脱出来,通过声明式方式灵活地进行事务的管理,提高开发效率和质量。
  • 方便程序的测试,可以用非容器依赖的编程方式进行几乎所有的测试工作。
  • 方便集成各种优秀框架,Spring提供了对各种优秀框架的直接支持

2002年,Rod Jahnson首次推出了Spring框架雏形interface21框架。

2004年3月24日,Spring框架以interface21框架为基础,经过重新设计,发布了1.0正式版。

Spring是一个轻量级的控制反转(IOC)和面向切面(AOP)的容器(框架)。 

1.2、Spring系统架构 

Spring的IOC和DI入门

Spring 框架是一个分层架构,由 7 个定义良好的模块组成。Spring 模块构建在核心容器之上,核心容器定义了创建、配置和管理 bean 的方式 .Spring的IOC和DI入门

2、Spring的IOC和DI入门
DI:依赖注入,一个BookService类的功能需要依赖另外一个BookDao类配合,同时需要附上一个具体的对象,则成这种关系是依赖注入;
IOC:控制反转,以前依赖的对象自己直接new,现在不需要new,框架会自动注入对象,创建对象的权利转移给了框架;  
Spring框架负责所有对象的创建、管理和依赖注入;所有的对象存储的容器叫做IOC容器;
3、 使用 spring 完成 IOC 的配置和 DI 依赖注入
3.1、创建项目,导入springjar包,按照如图创建接口及其实现类
Spring的IOC和DI入门

 Spring的IOC和DI入门

dao包 

1.接口BookDao

public interface BookDao {
    public void insert();
}

2.实现类BookDaoImpl

public class BookDaoImpl implements BookDao {

    @Override
    public void insert() {
        System.out.println("BookDaoImpl......insert");
    }
}

service包

1.接口BookService

public interface BookService {
    void save();
}

2.实现类BookServiceImpl

public class BookServiceImpl implements BookService {
    private String name;
    private BookDao bookDao;

    public void setName(String name) {
        this.name = name;
    }

    public void setBookDao(BookDao bookDao) {
        this.bookDao = bookDao;
    }

    @Override
    public void save() {
        System.out.println("BookServiceImpl......save+name");
        bookDao.insert();
    }
}

BookServiceImpl需要给bookDao属性设置setter方法,框架才能自动注入  

servlet包

servlet中进行测试

1.首先获取IOC的容器;

2.从容器中获取bookService对象;

3.执行方法:servlet执行---service执行,由于spring完成了依赖注入------dao包执行

public class BookServlet {
    BookService bookService;
    @Test
    public void add() {
        System.out.println("BookServlet...add");
        //1.获得IOC容器
        ClassPathXmlApplicationContext context=new ClassPathXmlApplicationContext("spring.xml");
        //2.根据名字从容器中获取对象
        bookService= (BookService) context.getBean("bookService");
        bookService.save();
    }
}

3.2、创建spring的核心配置文件

bean标签:把对应class的对象创建到IOC容器中,如果当前对象有依赖的其他对象,那么可以通过property对依赖的对象使用ref引用容器中已经注册过的对象。

把所有对象创建到spring的IOC容器中,并起上名字;id:表示给对象起名字 class:类的全类名
spring的依赖注入:
property表示BookServiceImpl的属性,常规属性使用value赋值,类型属性使用ref引用   
<?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.zhan.dao.impl.BookDaoImpl"></bean>
    <bean id="bookService" class="com.zhan.service.impl.BookServiceImpl">
        <property name="name" value="张三"/>
        <property name="bookDao" ref="bookDao"/>
    </bean>
</beans>

 控制台日志信息

Spring的IOC和DI入门

4.bean作用范围scope配置

singleton:单列,框架会唯一创建该对象,后续获取的都是同一个,在配置文件加载的时候创建了

prototype:非单例/多例,框架在每次获取的时候创建一个新的,在获得的时候创建。多线程

单例 

<bean id="bookService" class="com.zhan.service.impl.BookServiceImpl" scope="singleton">
        <property name="bookDao" ref="bookDao"/>
    </bean>

Spring的IOC和DI入门

多例 

<bean id="bookService" class="com.zhan.service.impl.BookServiceImpl" scope="prototype">
        <property name="bookDao" ref="bookDao"/>
    </bean>

 Spring的IOC和DI入门

 5.静态工厂实例化

 Spring的IOC和DI入门

factory:工厂对象;工厂类就是制造对象的,一般没有功能;

class:工厂类的全类名

factory-method:具体工厂类中创建对象的方法名

配置

<bean id="bookService3" class="com.zhan.factory.BookServiceFactory"></bean>

测试

public class Test02 {
    @Test
    public void test02(){
        ClassPathXmlApplicationContext context=new ClassPathXmlApplicationContext("spring.xml");
        BookServiceFactory factory = (BookServiceFactory) context.getBean("bookService3");
        System.out.println(factory);
    }
}

 日志信息

 Spring的IOC和DI入门

配置工厂

    <!--配置工厂,但是获得的工厂的商品 -->
    <bean id="bookService3" class="com.zhan.factory.BookServiceFactory" factory-method="getBean"></bean>

静态工厂创建对象

public class BookServiceFactory {
    public static BookService getBean(){
        return new BookServiceImpl();
    }
}

 测试类

public class Test02 {
    @Test
    public void test02(){
        ClassPathXmlApplicationContext context=new ClassPathXmlApplicationContext("spring.xml");
        BookService factory = (BookService) context.getBean("bookService3");
        System.out.println(factory);
    }
}

日志信息 

 Spring的IOC和DI入门

6.setter注入 

配置中使用property标签的ref属性注入引用类型对象

对于基本数据类型(包括String),指定属性值使用"value"属性,而对于引用类型使用"ref"属性。

<bean id="bookService" class="com.zhan.service.impl.BookServiceImpl" scope="singleton">
        <property name="bookDao" ref="bookDao"/>
    </bean>

在BookServiceImpl中定义引用类型属性,提供可访问的setter方法 

public class BookServiceImpl implements BookService {
    BookDao bookDao;

    public void setBookDao(BookDao bookDao) {
        this.bookDao = bookDao;
    }
}

7.构造器注入

使用constructor-arg标签进行依赖注入,name属性要与实现类中提供的形参类型和个数一致,否则将会报错。

<bean id="bookService1" class="com.zhan.service.impl.BookServiceImpl" scope="singleton">
        <constructor-arg name="name" value="张三"/>
        <constructor-arg name="bookDao" ref="bookDao"/>
    </bean>

 在BookServiceImpl中定义引用类型属性,提供有参的构造方法

public class BookServiceImpl implements BookService {
    String name;
    BookDao bookDao;

    public BookServiceImpl(String name, BookDao bookDao) {
        System.out.println("有参");
        this.name = name;
        this.bookDao = bookDao;
    }
}

8.集合注入

使用相应标签(list、set、array、map...)对属性值进行注入

    <bean id="bookService2" class="com.zhan.service.impl.BookServiceVip">
        <property name="list">
            <list>
                <value>张三</value>
                <value>张四</value>
                <value>张五</value>
            </list>
        </property>
        <property name="set">
            <set>
                <value>南阳</value>
                <value>信阳</value>
                <value>濮阳</value>
                <value>安阳</value>
                <value>开封</value>
                <value>郑州</value>
            </set>
        </property>
        <property name="map">
            <map>
                <entry key="name" value="张三"/>
                <entry key="age" value="20"/>
                <entry key="sex" value="男"/>
            </map>
        </property>
    </bean>

 在BookServiceVipl中定义引用类型属性,提供可访问的setter方法

public class BookServiceVip implements BookService {
    List<String> list;
    Set<String> set;
    Map<String,String> map;

    public void setList(List<String> list) {
        this.list = list;
    }

    public void setSet(Set<String> set) {
        this.set = set;
    }

    public void setMap(Map<String, String> map) {
        this.map = map;
    }

    @Override
    public String toString() {
        return "BookServiceVip{" +
                "list=" + list +
                ", set=" + set +
                ", map=" + map +
                '}';
    }
}

9.注解 

1.创建项目导入jar包

 Spring的IOC和DI入门Spring的IOC和DI入门

2.创建接口和实体类

配置文件

<?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:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/context
	   http://www.springframework.org/schema/context/spring-context.xsd">
    
    <!--让系统去扫描注解-->
    <context:component-scan base-package="com.zhan"/>
</beans>

自动注入

优先按照类型注入,如果有多个对象,按照名字进行注入

@Override:自动扫描器

@Autowired:自动注入属性

@Qualifier:指定名字进行注入

BookDaoImpl类使用注解 @Override

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

 BookServiceImpl类使用注解@Override ;@Autowired

@Component("bookService")
public class BookServiceImpl implements BookService {
    //自动注入优先按照类型注入,如果有多个对象,按照名字进行注入
    @Autowired
    BookDao bookDao;

    public void setBookDao(BookDao bookDao) {
        this.bookDao = bookDao;
    }

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

测试类

public class Test01 {
    BookService bookService;
    @Test
    public void test01(){
        ClassPathXmlApplicationContext context =new ClassPathXmlApplicationContext("spring.xml");
        //按照类型获得对象,前提类型有唯一的对象
        bookService = context.getBean(BookService.class);
        this.bookService.save();
    }
}

打印日志 

 Spring的IOC和DI入门