1.全注解下的Spring Ioc(控制反转)

Spring的控制反转(IoC),Spring最成功的是其提出的理念,而不是技术本身。

Spring的核心理念:

1.控制反转(Inversion of Control),简称IoC.

2.面向切面编程(Aspect Oriented Programming),简称AOP.

IoC是一种通过描述来生成或者获取对象发的技术,通常我们熟悉的就是通过new关键字来创建对象,但是在Spring中全部交给Spring来管理,通过描述来创建对象。

一个系统可以生成各种对象,并且这些对象都需要进行管理,对象之间并不是孤立的,它们之间还可能存在依赖的关系,例如,一个班级是由多个老师和同学组成的,那么班级本身就依赖于多个老师和同学了,所以Spring就提出了依赖注入的功能。

为了描述上述的班级、同学和老师这三个对象之间的关系,我们需要一个容器,在Spring中把每一个需要管理的对象称为Spring Bean (简称Bean),而Spring管理这些Bean的容器,被我们称为SpringIoC容器(简称IoC容器)。

IoC容器需要具备两个基本的功能:

1.通过描述管理Bean,包括发布和获取Bean。

2.通过描述完成Bean之间的依赖关系。

IoC容器简介

Spring IoC容器是一个管理Bean的容器,在Spring的定义中,所有的IoC容器都需要实现接口BeanFactory,它是一个顶级的容器接口。

以我项目中的以附件的方式发送邮件的项目pom为例:

pom.xml内容如下:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.bdyh</groupId>
    <artifactId>Email</artifactId>
    <version>1.0-SNAPSHOT</version>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.4.RELEASE</version>
        <relativePath/>
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.47</version>
        </dependency>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
            <version>3.0</version>
        </dependency>
        <dependency>
            <groupId>com.sun.mail</groupId>
            <artifactId>javax.mail</artifactId>
            <version>1.5.4</version>
        </dependency>
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

BeanFactory接口路径:

BeanFactory 接口源码:


  // IntelliJ API Decompiler stub source generated from a class file
  // Implementation of methods is not available

package org.springframework.beans.factory;

public interface BeanFactory {
    //前缀
    java.lang.String FACTORY_BEAN_PREFIX = "&";
    //多个getBean方法
    java.lang.Object getBean(java.lang.String s) throws org.springframework.beans.BeansException;

    <T> T getBean(java.lang.String s, @org.springframework.lang.Nullable java.lang.Class<T> aClass) throws org.springframework.beans.BeansException;

    java.lang.Object getBean(java.lang.String s, java.lang.Object... objects) throws org.springframework.beans.BeansException;

    <T> T getBean(java.lang.Class<T> aClass) throws org.springframework.beans.BeansException;

    <T> T getBean(java.lang.Class<T> aClass, java.lang.Object... objects) throws org.springframework.beans.BeansException;
    //是否包含Bean
    boolean containsBean(java.lang.String s);
    //Bean是否是单例
    boolean isSingleton(java.lang.String s) throws org.springframework.beans.factory.NoSuchBeanDefinitionException;
    //Bean是否是原型
    boolean isPrototype(java.lang.String s) throws org.springframework.beans.factory.NoSuchBeanDefinitionException;
    //是否类型匹配
    boolean isTypeMatch(java.lang.String s, org.springframework.core.ResolvableType resolvableType) throws org.springframework.beans.factory.NoSuchBeanDefinitionException;

    boolean isTypeMatch(java.lang.String s, @org.springframework.lang.Nullable java.lang.Class<?> aClass) throws org.springframework.beans.factory.NoSuchBeanDefinitionException;
    //获取Bean的类型
    @org.springframework.lang.Nullable
    java.lang.Class<?> getType(java.lang.String s) throws org.springframework.beans.factory.NoSuchBeanDefinitionException;
    //获取Bean的别名
    java.lang.String[] getAliases(java.lang.String s);
}

方法介绍:

多个getBean方法:从IoC容器中获取Bean,有按类型(by type)获取Bean的,有按名称(by name)获取Bean的。

isSingleton方法:判断Bean是否在Spring IoC中为单例,这里需要记住的是在Spring IoC容器中,默认的情况下,Bean都是以单例存在的,也就是使用getBean方法返回的都是同一个对象。与isSingleton方法相反的是isPrototype方法,如果它返回的是true,那么当我们使用getBean方法获取Bean的时候,Spring IoC容器就会创建一个新的Bean返回给调用者。

高级接口ApplicationContext:

由于BeanFactory的功能还不够强大,因此Spring在BeanFactory的基础上,设计了更为强大的接口ApplicationContent。它是BeanFactory的子接口之一,在Spring的体系中BeanFactory和ApplicationContext是最为重要的接口设计,在现实中我们使用的大部分Spring IoC容器是ApplicationContext接口的实现类。

查找路径:

关系图如下:

从Spring IoC容器的接口设计图中可以看到,ApplicationContext接口通过继承上级接口,进而继承BeanFactory接口,但是在BeanFactory的基础上,扩展了消息国际化接口(MessageSource)、环境可配置接口(EnvironmentCapable)、应用事件发布接口(ApplicationEventPublisher)和资源模式解析接口(ResourcePatternResolver),所以它的功能会更为强大。

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

1.首先定义一个Java简单对象 User.java。

package com.bdyh.entity;

/**
 * @author BD-PC40
 * @Title: User
 * @ProjectName Email
 * @Description: TODO
 * @date 2018/12/25 15:06
 */
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 com.bdyh.common;

import com.bdyh.entity.User;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @author BD-PC40
 * @Title: AppConfig
 * @ProjectName Email
 * @Description: 配置文件
 * @date 2018/12/25 15:28
 */
@Configuration
public class AppConfig {
    @Bean(name = "user")
    public User initUser() {
        User user = new User();
        user.setId(1L);
        user.setUserName("张三");
        user.setNote("note_1");
        return user;
    }
}

注解说明:

@Configuration:代表这是一个Java配置文件,Spring的容器会根据它来生成IoC容器去装配Bean.

@Bean:代表将initUser方法返回的POJO装配到IoC容器中,而其属性name定义这个Bean的名称,如果没有配置它,则将方法名称"initUser"作为Bean的名称保存到Spring IoC容器中。现在就可以用AnnotationConfigApplicationContext来构建自己的IoC容器。

使用AnnotationConfigApplicationContext:

package com.bdyh.common;


import com.bdyh.entity.User;
import org.apache.log4j.Logger;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

/**
 * @author BD-PC40
 * @Title: IoCTest
 * @ProjectName Email
 * @Description:
 * @date 2018/12/25 16:03
 */
public class IoCTest {
    private static Logger log = Logger.getLogger(IoCTest.class);
    public static void main(String[] args){
        ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);
        User user = ctx.getBean(User.class);
        log.info(user.getId());
    }
}

上述代码中将Java配置文件AppConfig传递给AnnotationConfigApplicationContext的构造方法,这样它就能够读取配置了。然后将配置里面的Bean装配到IoC容器中,于是可以用getBean方法获取对应POJO。

对应的日志打印:

16:25:48.484 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Returning cached instance of singleton bean 'org.springframework.context.event.internalEventListenerFactory'
16:25:48.541 [main] DEBUG org.springframework.context.annotation.AnnotationConfigApplicationContext - Unable to locate LifecycleProcessor with name 'lifecycleProcessor': using default [org.springframework.context.support.DefaultLifecycleProcessor@69b2283a]
16:25:48.541 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Returning cached instance of singleton bean 'lifecycleProcessor'
16:25:48.568 [main] DEBUG org.springframework.core.env.PropertySourcesPropertyResolver - Could not find key 'spring.liveBeansView.mbeanDomain' in any property source
16:25:48.571 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Returning cached instance of singleton bean 'user'

显然,配置在配置文件中的名称为user的Bean已经被装配到IoC的容器中了,并且可以通过getBean的方法获取对应的Bean,并将Bean的属性信息输出出来,当然这是很简单的方法,而注解@Bean也不是唯一创建Bean的方法,也可以通过其他的方法将Bean装配到IoC容器中

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小盒子_spring

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值