栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Spring的IoC和DI

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Spring的IoC和DI

Spring

Spring是分层的Java SE/EE应用full-stack轻量级开源框架,以IOC(翻转控制)和AOP(面向切面编程)为内核
提供了展现层SpringMVC和持久层Spring JDBCTemplatey以及业务层事务管理等众多的企业级应用技术,还能整合开源世界众多的第三方框架和类库,逐渐成为使用最多的Java EE企业级应用开源框架

Spring优势

1、方便解耦,简化开发
通过Spring提供的IOC容器,可以将对象间的依赖关系交由Spring进行控制,避免硬编码所造成的多度耦合,用户不必再为单例模式、属性文件解析等这些底层的需求编写代码,可以更专注于上层的应用
2、AOP编程的支持
通过Spring的AOP功能,方便进行面向切面编程,许多不容易用传统OOP实现的功能可以通过AOP轻松实现
3、声明式事务的支持
可以将我们从单调烦闷的事务代理代码中解脱出来,通过声明式灵活的进行事务管理,提高开发效率和质量
4、方便程序的测试
可以用非容器依赖的编程方式进行几乎所欲的测试工作,测试不再是昂贵的操作,而是随手可做的事情
5、方便继承各种优秀的框架
Spring对各种优秀的框架(Struts、Hibemate、Hessian、Quartz等)的支持
6、降低Java EE API的使用难度
Spring 对Java EE API(JDBC、JavaMail、远程调用等)进行了薄薄的封装,使用这些API的使用难度大为降低
7、Java源码是经典的学习范例
Spring的源代码设计精妙,结构清晰,匠心独具,处处体现着大师对Java设计模式灵活运用以及对Java技术的高深造诣

Spring体系结构

Spring程序开发步骤

1、导入Spring开发的基本包坐标

    

        
            org.springframework
            spring-context
            5.3.7
        

2、编写Dao接口和实现类
UserDao接口

package com.zg.dao;

public interface UserDao {
    public void save();
}

UserDao实现类

package com.zg.dao.impl;

import com.zg.dao.UserDao;

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

3、创建Spring核心配置文件




    

4、在Spring配置文件中配置UserDaoImpl


5、使用Spring的API获得Bean实例

package com.zg.demo;

import com.zg.dao.UserDao;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.context.support.GenericApplicationContext;

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

Spring配置文件详解 Bean标签基本配置

用于配置对象交由Spring来创建
默认情况下它调用的是类中的无参构造函数,如果没有无参构造函数则不能创建成功
id:Bean实例在Spring容器中的唯一标识
class:Bean的全限定名称

Bean标签范围配置

scope:指令对象的作用范围

1、当scope的取值为singleton时
Bean的实例化个数为1个
Bean的实例化时机:当Spring核心文件被加载时,实例化配置的Bean实例
Bean的声明周期:
对象创建:当应用加载,创建容器时,对象就被创建了
对象运行:只要容器在,对象一直活着
对象销毁:当应用卸载时,销毁容器时,对象就被销毁了

2、当scope的取值为prototype时
Bean的实例化个数为多个
Bean的实例化时机:当调用getBean()方法时,实例化配置的Bean实例
Bean的声明周期:
对象创建:当使用对象时,创建新的对象实例
对象运行:只要对象在使用中,对象一直活着
对象销毁:对象长时间不用,被Java的垃圾回收器回收

Bean生命周期配置
 

init-method:指定类中的初始化方法名称
destroy-method:指定类中销毁方法名称

Bean实例化三种方式

1、无参构造方法实例化
以上方式都为无参构造方法实例化

public class userDaoIMPL implements UserDao {

    public userDaoIMPL() {
    }
}


2、工厂静态方法实例化

package com.zg.factory;

import com.zg.dao.UserDao;
import com.zg.dao.impl.userDaoIMPL;
//工厂静态方法实例化
public class StaticFactory {

    public static UserDao getUserDao(){
        return new userDaoIMPL();

    }
}

在获取全类名时可以右键其名称选择Copy Reference
3、工厂实例方法实例化,很多


    
    
    
package com.zg.factory;

import com.zg.dao.UserDao;
import com.zg.dao.impl.userDaoIMPL;
//工厂静态方法实例化
public class StaticFactory {

    public static UserDao getUserDao(){
        return new userDaoIMPL();

    }
}

Spring配置文件 创建service层,不使用Spring

当我们不使用Spring,在service层中我们需要通过UserServiceImpl实现类来重写UserService中的save()方法,然后调用通过Spring获取Dao层中UserDao的实现类UserDaoImpl对象的save方法(业务层save调用Dao层save),然后web层中通过UserService userService = new UserServiceImpl(); 获取service,来实现dao层的具体业务,这里因为service层没有配置到Spring容器中。
1、创建UserService,UserServie内部调用UserDao的save()方法

package com.zg.service.impl;

import com.zg.dao.UserDao;
import com.zg.service.UserService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class UserServiceImpl implements UserService {
    @Override
    public void save() {
        //UserService要调UserDao,但现在UserDao已经在Spring产生
        ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
        UserDao userDao = (UserDao)app.getBean("userDao");
        userDao.save();

    }
}

2、web层不使用Spring来封装service

package com.zg.demo;

import com.zg.service.UserService;
import com.zg.service.impl.UserServiceImpl;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class UserController {
    //它的内部需要获得Service
    public static void main(String[] args) {
        //不使用Spring封装service
        UserService userService = new UserServiceImpl();
        userService.save();
    }

}
将service层也配置到Spring容器中

1、在配置文件applicationContext.xml中将UserServiceImpl的创建权交给Spring


2、从Spring容器中获得UserService进行操作

package com.zg.demo;

import com.zg.service.UserService;
import com.zg.service.impl.UserServiceImpl;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class UserController {
    //它的内部需要获得Service
    public static void main(String[] args) {
        //使用Spring封装service
        ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
        UserService userService = (UserService) app.getBean("userService");
        userService.save();
    }

}

问题分析

目前UserSrvice实例和UserDao实例都存在于Spring中,当前的做法是在容器外部获取UserService实例和UserDao实例,然后再程序中进行结合

因为UserService和UserDao都在Spring容器中,而最终程序直接使用的是UserService,所以可以在Spring容器中,将UserDao设置到UserService内部

Bean的依赖注入概念

依赖注入(Dependency Injection):它是Spring框架核心IOC的具体实现

在编写程序时,通过控制反转,把对象的创建交给了Spring,但是代码中不可能出现没有依赖的情况。
IOC解耦只是降低他们之间的关系,但不会消除(业务层仍然会调用持久层的方法)

那这种业务层和持久层的依赖关系,在使用Spring后,使用Spring来维护,也就是等框架把持久层对象传入入业务层,不用我们获取

Bean的依赖注入方式

将UserDao注入到UserService内部可通过有参的构造方法和set方法来实现

set方法注入(注入对象)

1、在UserServiceImpl中添加setUserDao方法

package com.zg.service.impl;

import com.zg.dao.UserDao;
import com.zg.service.UserService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class UserServiceImpl implements UserService {

    private UserDao userDao;
    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }

    @Override
    public void save() {
       
        //我们不用从容器获取Dao,因为在容器内部已经将Dao通过set方法注入给了service
        userDao.save();

    }
}

2、配置Spring容器中调用set方法进行注入

 
 
        
        
        
        
    

但是但是,在web层就不能new一个UserService啦,因为它没有获取UserDao的注入,所以在web层只能使用通过Spring封装的service来调用dao的方法

set方法注入的简单方式–>P命名空间注入

P命名空间注入的本质也是set方法注入,但比起上述的set方法注入更加方便,主要体现在配置文件中

xmlns:p="http://www.springframework.org/schema/p"


然后将下面的代码1进行更换为代码2就行
代码1:

 
 
        
        
        
        
    

代码2:


构造注入(有参构造)

1、创建有参构造

package com.zg.service.impl;

import com.zg.dao.UserDao;
import com.zg.service.UserService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class UserServiceImpl implements UserService {

    private UserDao userDao;//有参构造
    public UserServiceImpl(UserDao userDao) {
        this.userDao = userDao;
    }

    public UserServiceImpl() {//无参构造
    }
    

    @Override
    public void save() {
      
        //我们不用从容器获取Dao,因为在容器内部已经将Dao通过set方法注入给了service
        userDao.save();

    }
}

2、构造方法注入


 
    
        
        
    
Bean的依赖注入的数据类型

set和有参构造方法都是注入的引用Bean,除了对象的引用可以注入,普通数据类型,集合等都可以在容器中进行注入
注入数据的三种数据类型
普通数据类型
引用数据类型
集合数据类型

以set方法注入为例,演示普通数据类型和集合数据类型的注入 普通数据类型的注入
package com.zg.dao.impl;

import com.zg.dao.UserDao;

public class userDaoImpl implements UserDao {

    private String username;
    private int age;

    public void setUsername(String username) {
        this.username = username;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public void save() {
        System.out.println(username+"===="+age);
        System.out.println("save runningg.....");
    }

}


        
        
        
    
集合数据类型的注入
package com.zg.dao.impl;

import com.zg.dao.UserDao;
import com.zg.domain.User;

import java.util.List;
import java.util.Map;
import java.util.Properties;

public class userDaoImpl implements UserDao {

    private List strList;
    private Map userMap;
    private Properties properties;

    public void setStrList(List strList) {
        this.strList = strList;
    }

    public void setUserMap(Map userMap) {
        this.userMap = userMap;
    }

    public void setProperties(Properties properties) {
        this.properties = properties;
    }

    private String username;
    private int age;

    public void setUsername(String username) {
        this.username = username;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public void save() {
        //System.out.println(username+"===="+age);
        System.out.println("save runningg.....");
        System.out.println(strList);
        System.out.println(userMap);
        System.out.println(properties);
    }

}


        
        
            
            
            aaa
                bbb
                ccc
            
        
        
            
            
                
                
                
                
            
        

        
            
                ppp1
                ppp3
                ppp4

            
        

    

            
                
                
            

            
                
                
            

Map集合中准备的user

package com.zg.domain;

public class User {
    private String name;
    private String addr;

    public String getName() {
        return name;
    }

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

    public String getAddr() {
        return addr;
    }

    public void setAddr(String addr) {
        this.addr = addr;
    }

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + ''' +
                ", addr='" + addr + ''' +
                '}';
    }
}

引入其他配置文件(分模块开发)

实际开发中,Spring的配置内容非常多,这就导致Spring配置很繁杂且体积很大,所以,可以将部分配置拆解到其他配置文件中,而在Spring主配置文件通过import标签进行加载



如果不使用set方法注入而使用构造方法引用,则标签和标签内部的配置写法一样。

Spring相关API ApplicationContext的继承体系

applicationContext:接口类型,代表应用上下文,可以通过其实例获得Spring容器中的Bean对象

ApplicationContext的实现类

1、ClassPathXmlApplicationContext:从类的根路径下加载配置文件推荐使用

 ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");

2、FileSystemXmlApplicationContext:从磁盘路径上加载配置文件,配置文件可以在磁盘的任意位置
在项目名称上右键选择Copy path即可复制文件在磁盘上的路径

FileSystemXmlApplicationContext fileSystemXmlApplicationContext = new FileSystemXmlApplicationContext("D:\java\Spring\src\main\resources\applicationContext.xml");

3、AnnotationConfigApplicationContext:使用注解配置容器对象时,需要使用此类来创建spring容器,用来读取注解

getBean()方法的使用

使用ID:UserService userService = (UserService) app.getBean("userService");允许容器中存在相同类型的Bean
使用字节码类型:UserService userService1 = app.getBean(UserService.class);

其中,当参数的数据类型是字符串时,表示根据Bean的id从容器中获得Bean实例,返回是Object,需要强转。当参数的数据类型是Class时,表示根据类型从容器中匹配Bean实例,当容器中相同类型的Bean有多个时,则此方法会报错。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/351327.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号