Spring-IOC

发布时间 2023-12-21 23:37:31作者: 学Java的`Bei

 

1. 前言

  1) 框架:

    spring的本质就是一个容器,放java对象的容器,java对象在spring容器中也叫做bean对象。

    项目启动的时候,把bean对象放到IOC容器中,当需要使用对象的时候,直接从容器中拿出来使用。

  2) 框架作用:

    •  提高开发效率;
    •  增强可重用性;
    •  提供编写规范;
    •  节约维护成本;
    •  解耦底层实现原理。  

  3) Spring:

    提高了开发效率,但降低了运行效率。

    Spring使程序员专注于写业务代码;

    Spring是分层的JavaEE/SE应用full-stack  轻量级,开源的,半成品框架,以IOC(Inverse Of Control:控制反转)和AOP(Aspect Oriented ProGramming:面向切面对象)为内核!

    分层:视图层,逻辑层,持久层。

      •  JAVASE/EE
      •  full-stack
      •  轻量级
      •  开源

    DDD分层架构:(三层架构分离) SpringCloud使用。

    Spring体系结构:

    • 底层是核心容器:

      Beans;

      Core-核心;

      Context-上下文;

      SpringEI表达式;
      Bean就是Java对象。

    • 中间层级数:

      AOP-面向切面(通俗讲就是将重复的代码放入业务代码内);

      Aspects;

    • 应用层对象:

      数据访问与数据集成;

      Web集成;

      Web实现;

      Web就是网页开发。

    • 基于Test测试。

 

    Transactions-事务

  【笔试】事务应具有4个属性:原子性,一致性,隔离性,持久性

 

  4) Spring优势:

      •  方便解耦,简化开发。
      •  方便集成各种优秀框架。
      •  方便程序的测试。
      •  切面编程的支持。
      •  声明式事务的支持@Transactional
      •  降低JavaEE API 的使用难度

2. IOC 控制反转

  1)概念:

    IOC全称(Inverse Of Control)为“控制反转”,也叫 DI (Dependency Injection),即依赖注入。本质功能就是:由Spring IOC 容器来负责对象的生命周期和对象之间的关系。

    在使用框架前书写的都是原生代码;

    而原生代码现状:耦合度太高,我们修改一处代码,往往要修改很多出相关联的代码。

    Spring技术对此提供的实现;
    Spring提供了一个容器,称为IOC容器,用来充当IOC思想中的外部。
    IOC容器负责对象的创建、初始化等一系列工作,被创建或被管理的对象在IOC容器中统称为Bean。

    控制反转:控制对象的创建;使用对象时候由主动new对象转换成由外部提供对象,此过程中对象的创建权由程序转移到外部。
    引出IOC(控制反转);对象的创建权由程序转移到外部,这种思想叫做控制反转。
  

 

    DI(依赖注入):在容器中建立bean与bean之间的依赖关系的整个过程。
            总的来说,依赖注入使得代码更具可扩展性、可维护性,同时也更容易实现松耦合的设计。

 

    类生命周期:加载、(验证,准备,解析)-连接、初始化、使用、卸载七流程。

 

  2)新建项目:

    Meven:jar包管理工具。

 

        HTML:超文本标记语言。
           XML:可扩展标记语言。

    IDea 新建 项目:

    

     创建完后 右上角 new file  settings:

    将此处的  file conf --> settings  与 repository仓库 更改。

    

     改完后:Apply --> ok

  如下:

    

  Run 一下 Main :

  

  配置的很完美!

 

 

 

 

  3):案例--属性注入

     导入 Spring 开发的基本包坐标

  在 Pom.xml 内配置

    <dependencies>
        <!--导入spring的context坐标,context依赖core、beans、expression-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <!--   此处可更改maven版本   -->
            <version>5.0.5.RELEASE</version>
        </dependency>
    </dependencies>

 

  

  (导入依赖 若背景变黄为有漏洞,可查找没有漏洞的导入)

   编写 Dao 接口和实现类

  在 Java 下 创建三级目录 dao包 在 dao下新建 IUserDao 接口

  dao 创建 Impl包,接口与Impl包为同级,在 Impl 包里写 接口实现类。

public interface IUserDao {
        void say();
}

 

public class UserDaoImpl implements IUserDao {
    
    @Override
    public void say() {
        System.out.println("Hello IOC!");
        System.out.println("Maven:我这一生如履薄冰!");
    }
}

 

  

 

   创建 Spring 核心配置文件  application.xml

 

    

 

 

  ④ 在 Spring 配置文件中配置 UserDaoImpl

<?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-4.0.xsd">
<!--   在Spring配置文件中 配置UserDaoImpl  -->
    <bean id="UserDaoImpl" class="org.example.dao.impl.UserDaoImpl"></bean>

 

  

 

  ⑤  Main:使用 Spring 的 API 获得 Bean 实例

public class Main {
    public static void main(String[] args) {
//        使用Spring的API获取Bean实例
//        获取配置文件的上下文信息
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("application.xml");
        UserDaoImpl userDao = context.getBean(UserDaoImpl.class);
        userDao.say();
    }
}

 

 

  

   控制台输出:

  

 

  4)Bean标签解析:

  

    id:Bean实例在Spring容器中的唯一标识。

    class:Bean的完全限定名。  

    scope范围配置:

      •  scope="singleton/prototype"(singleton-单例(默认)、prototype-多例)
      •  当Bean实例化个数只有一个时,在Spring配置文件加载时,对象就被创建了。
      •  当Bean实例化个数为多个时,在调用getBean才会创建对象。

    注意:Bean对象实例化都是Spring调用对象的 无参构造 方法。
    当构造方法执行结束后对象就被创建出来了。

  5)生命周期

      当scope的取值为singleton时(系统默认),Bean的实例化个数:1个。

          •  Bean的实例化时机:当Spring核心文件被加载时,实例化配置的Bean实例;
          •  Bean的生命周期: 对象创建:当应用加载,创建容器时,对象就被创建了;
          •  对象运行:只要容器在,对象一直活着;
          •  对象销毁:当应用卸载,销毁容器时,对象就被销毁了。

       当scope的取值为prototype时,Bean的实例化个数:多个。

          •  Bean的实例化时机:当调用getBean()方法时实例化Bean;
          •  对象创建:当使用对象时,创建新的对象实例;
          •  对象运行:只要对象在使用中,就一直活着;
          •  对象销毁:当对象长时间不用时,被 Java 的垃圾回收器回收了( jvm gc垃圾回收

        注意: 以上bean对象实例化都是spring调用对象的无参构造方法。

3. DI 依赖注入

    两种方式:set注入 构造注入

    依赖: 两个对象之间的关系;比如service想要调用dao的方法,那么service里就需要dao对象,这就是依赖。

    注入:就是将dao给了service的过程,在spring的容器中,注入是容器给完成的。

    set 注入

    必须有set方法,注意注入的方式是set方式,但是主动执行的人是spring容器。

      例:通过service调用dao的方法

     新建 service 层,在service层里新建 IUserService接口,在service层里新建 包 Impl,Impl包里新建 ImplUserServiceImpl 接口实现类:

      (所有的层 都是同级的,所有的Impl 都是在 层 下,与 接口同级)

      

public interface IUserService {
    void save();
}
public class UserServiceImpl implements IUserService {

    private IUserDao iUserDao;
    
//    依赖注入-set
    public void setiUserDao(IUserDao iUserDao) {
        this.iUserDao = iUserDao;
    }
    
    @Override
    public void save() {
        iUserDao.say();
    }
}

      

    ②  在 Spring (application.xml)配置文件中配置 UserServiceImpl

<!--&lt;!&ndash; 依赖注入-set &ndash;&gt;-->
    <bean id="UserServiceImpl" class="org.example.service.impl.UserServiceImpl">
<!--   ref-外部引用   -->
    <property name="iUserDao" ref="UserDaoImpl"/>
    </bean>

      

      Main:使用 Spring 的 API 获得 Bean 实例

public class Main {
    public static void main(String[] args) {
//        使用Spring的API获取Bean实例
//        获取配置文件的上下文信息
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("application.xml");
//        依赖注入-set
        UserServiceImpl userService = context.getBean(UserServiceImpl.class);
        userService.save();
    }
}

      

   控制台输出:

      

 

4. 注解开发

     注解开发:

注解 说明
@Component 使用在类上用于实例化Bean
@Controller 使用在web层类上用于实例化Bean
@Service 使用在service层类上用于实例化Bean
@Repository 使用在dao层类上用于实例化Bean
@Autowired 使用在字段上用于根据类型依赖注入
@Qualifier 结合@Autowired一起使用用于根据名称进行依赖注入
@Resource 相当于@Autowired+@Qualifier,按照名称进行注入
@Value 注入普通属性

     注意: 一般用autowired注解,因为spring默认都是单例模式,所以也很少和Qualifier配合使用。Resource如果注入的对象不存在会抛出异常。

     扫描(application.xml)包下的组件(注解): 

<!-- 注解开发 -->
    <context:component-scan base-package="org.example"></context:component-scan>

    

      新建 pojo 层,新建 User 类,并写入注解:

@Component("User") // 实例化Bean
public class User {
    @Value("1")     // 注入普通属性
    private Integer id;
    @Value("刘备")
    private String name;
    @Value("20")
    private Integer age;
    @Value("帅哥")
    private String sex;

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", age=" + age +
                ", sex='" + sex + '\'' +
                '}';
    }
}

    

     并分别在 dao 层、service 层添加注解:

@Repository("IUserDao")
public interface IUserDao {
        void say();
}
// Dao层类实例化Bean
@Repository("IUserDao")
public class UserDaoImpl implements IUserDao {

// 使用在字段上用于根据类型依赖注入
    @Autowired
    private User user;
    @Override
    public void say() {
        System.out.println("Hello IOC!");
        System.out.println("Maven:我这一生如履薄冰!");
        System.out.println(user);
    }
}
// 在service层类上用于实例化Bean
@Service("IUserService")
public class UserServiceImpl implements IUserService {

//    使用在字段上用于根据类型依赖注入 结合@Autowired一起使用用于根据名称进行依赖注入
@Autowired
@Qualifier("IUserDao")
    private IUserDao iUserDao;
    @Override
    public void save() {
        iUserDao.say();
    }
}
public class Main {
    public static void main(String[] args) {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("application.xml");
        UserServiceImpl userService = context.getBean(UserServiceImpl.class);
        userService.save();
    }
}

  控台输出: