Spring IoC全注解开发-IoC容器简介

本章先探讨Spring 的控制反转(IoC)的应用。Spring所依赖的两个核心理念,一个是控制反转(Inversion of
Controller),另一个是面向切面编程(Aspect Oriented Programming,AOP)。

IoC容器是Spring的核心,可以说Spring是一种基于IoC容器编程的框架。因为Spring Boot是基于注解的开发Spring
IoC,所以我们使用全注解的方式讲述Spring Ioc技术,为后续章节打下基础。

一个系统可以生成各种对象,并且这些对象都需要进行管理。还值得一提的是,对象之间并不是孤立的,他们之间可能存在依赖的关系。例如,一个班级由多个老师和同学构成,那么班级就依赖于多个老师和同学。为此Spring还提供了依赖注入的功能,使得我们能够通过描述来管理各个对象之间的关系。

为了描述上述的把班级,同学,老师之间的关系,我们需要一个容器。在Spring中把每一个需要管理的对象称为Spring
Bean(简称Bean),而Spring 管理这些bean的容器,被我们称为Spring
IOC容器(或者简称IoC容器)。IoC容器具备两个基本功能:
- 通过描述管理Bean,包括发布和获取Bean;
- 通过描述完成Bean之间的依赖关系 使用Bean之前,需要对Spring Ioc容器有一个基本的认识。

IoC容器简介

Spring
IoC容器是一个管理Bean的容器,在Spring的定义中,他要求所有的IoC容器都实现接口BeanFactory,他是一个顶级容器接口。为了增加对其的理解,我们首先阅读其源码,并讨论几个重要方法。

  • BeanFactory接口源码
/*
 * Copyright 2002-2019 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.springframework.beans.factory;

import org.springframework.beans.BeansException;
import org.springframework.core.ResolvableType;
import org.springframework.lang.Nullable;

//我在源码里面找的.5.2.5
public interface BeanFactory {

//前缀
	String FACTORY_BEAN_PREFIX = "&";
//多个getBean方法
	Object getBean(String name) throws BeansException;
	<T> T getBean(String name, Class<T> requiredType) throws BeansException;
	Object getBean(String name, Object... args) throws BeansException;
	<T> T getBean(Class<T> requiredType) throws BeansException;
	<T> T getBean(Class<T> requiredType, Object... args) throws BeansException;
	<T> ObjectProvider<T> getBeanProvider(Class<T> requiredType);
	<T> ObjectProvider<T> getBeanProvider(ResolvableType requiredType);
//是否包含Bean
	boolean containsBean(String name);
//Bean是否是单例
	boolean isSingleton(String name) throws NoSuchBeanDefinitionException;
//Bean是否是原型
	boolean isPrototype(String name) throws NoSuchBeanDefinitionException;
//是否类型匹配
	boolean isTypeMatch(String name, ResolvableType typeToMatch) throws NoSuchBeanDefinitionException;
//是否类型匹配
	boolean isTypeMatch(String name, Class<?> typeToMatch) throws NoSuchBeanDefinitionException;
//获取Bean的类型
	@Nullable
	Class<?> getType(String name) throws NoSuchBeanDefinitionException;
//这是新加的一个属性
	@Nullable
	Class<?> getType(String name, boolean allowFactoryBeanInit) throws NoSuchBeanDefinitionException;
//获取bean的别名
	String[] getAliases(String name);

}

这段代码加入了中文注释,通过他们就可以理解这些方法的含义。值得注意的是接口中的几个方法,首先我们看到的是多个getBean的方法,这也是IoC容器最重要的方法之一,他的意义是从Ioc容器中获取Bean。而从多个getBean方法中可以看到有按照类型(by type)获取,也有按照名称获取(by name),这就意味着在Spring IoC容器中,允许我们按照类型或者名称获取bean,这对后面理解即将讲到的Spring的依赖注入(Dependency Injection,DI)是非常重要的。

isSingleton方法则判断Bean是否在Spring IoC中为单例。需要记住的是Spring
IOC容器中。默认情况下,Bean都是以单例存在的,也就是使用getBean方法返回的都是同一个对象。与isSingleton相反的是isPrototype方法,他返回的是true,那么当我们使用getBean方法获取Bean的时候Spring IOC容器就会创建一个新的Bean返回给调用者,这些与后面将要讨论轮的bean的作用域有关。

ApplicationContext是BeanFactory的子接口之一,在Spring体系中ApplicationCOntext和BeanFactory是最为重要的接口设计,在现实中我们使用的大部分Spring IOC容器是ApplicationContext接口的实现类,他们的接口关系如下。

在这里插入图片描述

在途中可以看到,ApllicationContext接口通过继承上级接口,进而继承BeanFactory接口,但是在BeanFactory的基础上消息国际化接口(MessageSource),环境可配值接口登。

在Spring Boot当中我们主要是通过注解来装配Bean到SpringIoC容器中,为了贴近SpringBoot的需要,主要介绍一个基于注解的IOC容器。

他就是AnnotationConfigApplicationContext,从名称就可以看出他是一个基于注解的IOC容器。之所以研究他是因为Spring Boot的装配和他如出一辙。 下面一个例子,首先定义一个Java普通对象(plain Ordinary Java Object,POJO)文件User.java,代码清单如下。

package cn.hctech2006.boot.bootall.bean;

public class User {
    private Long id;
    private String userName;
    private String note;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public String getNote() {
        return note;
    }

    public void setNote(String note) {
        this.note = note;
    }
}

然后在定义一个Java配置文件AppConfig.java
package cn.hctech2006.boot.bootall.config;

import cn.hctech2006.boot.bootall.bean.User;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class AppConfig {
    @Bean(name = "user")
    public User initUser(){
        User user = new User();
        user.setId(1L);
        user.setUserName("USER_NAME_1");
        user.setNote("NOTE_1");
        return user;
    }
}

注意@Configuration代表这是一个Java配置文件,Spriong的容器会根据他来生成IOC容器去装配Bean;
@Bean代表将initUser方法返回的POJO装配到IOC容器中,而其属性name定义这个Bean的别称,如果没有配置他,则将方法名称“initUser”作为Bean的名称保存到Spring IOC容器中。
做好这些就可以使用AnnotationConfigApplicationContext来构建自己的IOC容器了,代码清单如图所示。

package cn.hctech2006.boot.bootall.context;

import cn.hctech2006.boot.bootall.bean.User;
import cn.hctech2006.boot.bootall.config.AppConfig;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

import java.util.logging.Logger;

public class IoCTest {
    private static Logger log = Logger.getLogger(String.valueOf(IoCTest.class));
    public static void main(String[] args){
        ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);
        User user = ctx.getBean(User.class);
        log.info(user.getUserName());
    }
}

代码中将java配置文件AppConfig传递给AnnotationConfigApplicationCpntext的构造方法,这样他就能够读取配置位置了。然后将配置里面的Bean装配到IoC容器中,于是可以使用getBean方法获取对应的POJO,你可以看到下面的日志打印。

/usr/lib/jdk/bin/java -javaagent:/usr/local/software/idea/idea-IU-193.5662.53/lib/idea_rt.jar=46421:/usr/local/software/idea/idea-IU-193.5662.53/bin -Dfile.encoding=UTF-8 -classpath /usr/lib/jdk/jre/lib/charsets.jar:/usr/lib/jdk/jre/lib/deploy.jar:/usr/lib/jdk/jre/lib/ext/cldrdata.jar:/usr/lib/jdk/jre/lib/ext/dnsns.jar:/usr/lib/jdk/jre/lib/ext/jaccess.jar:/usr/lib/jdk/jre/lib/ext/jfxrt.jar:/usr/lib/jdk/jre/lib/ext/localedata.jar:/usr/lib/jdk/jre/lib/ext/nashorn.jar:/usr/lib/jdk/jre/lib/ext/sunec.jar:/usr/lib/jdk/jre/lib/ext/sunjce_provider.jar:/usr/lib/jdk/jre/lib/ext/sunpkcs11.jar:/usr/lib/jdk/jre/lib/ext/zipfs.jar:/usr/lib/jdk/jre/lib/javaws.jar:/usr/lib/jdk/jre/lib/jce.jar:/usr/lib/jdk/jre/lib/jfr.jar:/usr/lib/jdk/jre/lib/jfxswt.jar:/usr/lib/jdk/jre/lib/jsse.jar:/usr/lib/jdk/jre/lib/management-agent.jar:/usr/lib/jdk/jre/lib/plugin.jar:/usr/lib/jdk/jre/lib/resources.jar:/usr/lib/jdk/jre/lib/rt.jar:/home/lidengyin/Downloads/code/boot-all/target/classes:/home/lidengyin/.m2/repository/org/springframework/boot/spring-boot-starter-aop/2.2.4.RELEASE/spring-boot-starter-aop-2.2.4.RELEASE.jar:/home/lidengyin/.m2/repository/org/springframework/spring-aop/5.2.3.RELEASE/spring-aop-5.2.3.RELEASE.jar:/home/lidengyin/.m2/repository/org/springframework/spring-beans/5.2.3.RELEASE/spring-beans-5.2.3.RELEASE.jar:/home/lidengyin/.m2/repository/org/aspectj/aspectjweaver/1.9.5/aspectjweaver-1.9.5.jar:/home/lidengyin/.m2/repository/org/springframework/boot/spring-boot-starter-web/2.2.4.RELEASE/spring-boot-starter-web-2.2.4.RELEASE.jar:/home/lidengyin/.m2/repository/org/springframework/boot/spring-boot-starter-json/2.2.4.RELEASE/spring-boot-starter-json-2.2.4.RELEASE.jar:/home/lidengyin/.m2/repository/com/fasterxml/jackson/core/jackson-databind/2.10.2/jackson-databind-2.10.2.jar:/home/lidengyin/.m2/repository/com/fasterxml/jackson/core/jackson-annotations/2.10.2/jackson-annotations-2.10.2.jar:/home/lidengyin/.m2/repository/com/fasterxml/jackson/core/jackson-core/2.10.2/jackson-core-2.10.2.jar:/home/lidengyin/.m2/repository/com/fasterxml/jackson/datatype/jackson-datatype-jdk8/2.10.2/jackson-datatype-jdk8-2.10.2.jar:/home/lidengyin/.m2/repository/com/fasterxml/jackson/datatype/jackson-datatype-jsr310/2.10.2/jackson-datatype-jsr310-2.10.2.jar:/home/lidengyin/.m2/repository/com/fasterxml/jackson/module/jackson-module-parameter-names/2.10.2/jackson-module-parameter-names-2.10.2.jar:/home/lidengyin/.m2/repository/org/springframework/boot/spring-boot-starter-tomcat/2.2.4.RELEASE/spring-boot-starter-tomcat-2.2.4.RELEASE.jar:/home/lidengyin/.m2/repository/org/apache/tomcat/embed/tomcat-embed-websocket/9.0.30/tomcat-embed-websocket-9.0.30.jar:/home/lidengyin/.m2/repository/org/springframework/boot/spring-boot-starter-validation/2.2.4.RELEASE/spring-boot-starter-validation-2.2.4.RELEASE.jar:/home/lidengyin/.m2/repository/jakarta/validation/jakarta.validation-api/2.0.2/jakarta.validation-api-2.0.2.jar:/home/lidengyin/.m2/repository/org/hibernate/validator/hibernate-validator/6.0.18.Final/hibernate-validator-6.0.18.Final.jar:/home/lidengyin/.m2/repository/org/jboss/logging/jboss-logging/3.4.1.Final/jboss-logging-3.4.1.Final.jar:/home/lidengyin/.m2/repository/com/fasterxml/classmate/1.5.1/classmate-1.5.1.jar:/home/lidengyin/.m2/repository/org/springframework/spring-web/5.2.3.RELEASE/spring-web-5.2.3.RELEASE.jar:/home/lidengyin/.m2/repository/org/springframework/spring-webmvc/5.2.3.RELEASE/spring-webmvc-5.2.3.RELEASE.jar:/home/lidengyin/.m2/repository/org/springframework/spring-context/5.2.3.RELEASE/spring-context-5.2.3.RELEASE.jar:/home/lidengyin/.m2/repository/org/springframework/spring-expression/5.2.3.RELEASE/spring-expression-5.2.3.RELEASE.jar:/home/lidengyin/.m2/repository/org/springframework/boot/spring-boot-starter/2.2.4.RELEASE/spring-boot-starter-2.2.4.RELEASE.jar:/home/lidengyin/.m2/repository/org/springframework/boot/spring-boot/2.2.4.RELEASE/spring-boot-2.2.4.RELEASE.jar:/home/lidengyin/.m2/repository/org/springframework/boot/spring-boot-autoconfigure/2.2.4.RELEASE/spring-boot-autoconfigure-2.2.4.RELEASE.jar:/home/lidengyin/.m2/repository/org/springframework/boot/spring-boot-starter-logging/2.2.4.RELEASE/spring-boot-starter-logging-2.2.4.RELEASE.jar:/home/lidengyin/.m2/repository/ch/qos/logback/logback-classic/1.2.3/logback-classic-1.2.3.jar:/home/lidengyin/.m2/repository/ch/qos/logback/logback-core/1.2.3/logback-core-1.2.3.jar:/home/lidengyin/.m2/repository/org/apache/logging/log4j/log4j-to-slf4j/2.12.1/log4j-to-slf4j-2.12.1.jar:/home/lidengyin/.m2/repository/org/apache/logging/log4j/log4j-api/2.12.1/log4j-api-2.12.1.jar:/home/lidengyin/.m2/repository/org/slf4j/jul-to-slf4j/1.7.30/jul-to-slf4j-1.7.30.jar:/home/lidengyin/.m2/repository/jakarta/annotation/jakarta.annotation-api/1.3.5/jakarta.annotation-api-1.3.5.jar:/home/lidengyin/.m2/repository/org/springframework/spring-core/5.2.3.RELEASE/spring-core-5.2.3.RELEASE.jar:/home/lidengyin/.m2/repository/org/springframework/spring-jcl/5.2.3.RELEASE/spring-jcl-5.2.3.RELEASE.jar:/home/lidengyin/.m2/repository/org/yaml/snakeyaml/1.25/snakeyaml-1.25.jar:/home/lidengyin/.m2/repository/org/slf4j/slf4j-api/1.7.30/slf4j-api-1.7.30.jar:/home/lidengyin/.m2/repository/org/apache/tomcat/embed/tomcat-embed-core/9.0.30/tomcat-embed-core-9.0.30.jar:/home/lidengyin/.m2/repository/org/apache/tomcat/tomcat-annotations-api/9.0.30/tomcat-annotations-api-9.0.30.jar:/home/lidengyin/.m2/repository/org/apache/tomcat/embed/tomcat-embed-el/9.0.30/tomcat-embed-el-9.0.30.jar:/home/lidengyin/.m2/repository/javax/servlet/jstl/1.2/jstl-1.2.jar cn.hctech2006.boot.bootall.context.IoCTest
11:37:26.617 [main] DEBUG org.springframework.context.annotation.AnnotationConfigApplicationContext - Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@61064425
11:37:26.629 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.annotation.internalConfigurationAnnotationProcessor'
11:37:26.703 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.event.internalEventListenerProcessor'
11:37:26.705 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.event.internalEventListenerFactory'
11:37:26.706 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.annotation.internalAutowiredAnnotationProcessor'
11:37:26.707 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.annotation.internalCommonAnnotationProcessor'
11:37:26.712 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'appConfig'
11:37:26.717 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'user'
四月 09, 2020 11:37:26 上午 cn.hctech2006.boot.bootall.context.IoCTest main
信息: USER_NAME_1

Process finished with exit code 0

显示在配置文件中的名称为appconfig,user的Bean已经被装配到IoC容器,并且可以通过getBean方法获取对应的Bean,并将Bean的属性信息输出出来。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值