前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Spring学习(1)——IoC部分

Spring学习(1)——IoC部分

作者头像
玛卡bug卡
发布2022-09-20 11:04:38
4740
发布2022-09-20 11:04:38
举报
文章被收录于专栏:Java后端修炼

1、概述

Spring框架是一个开源的、松耦合的、分层的、可配置的一站式企业级 Java 开发框架,它的核心是IoC(控制反转)和AOP(面向切面编程)。在Spring中,构成应用程序主干并由 Spring IoC 容器管理的对象称为bean。bean 是由IoC容器实例化,组装和以其他方式管理的对象。

IoC是一种思想,核心是将控制权转交出去,实际上指的就是本来由程序员手动创建bean的工作交由Spring进行创建,而放置和管理这些bean的就是IoC容器。程序员可以将对象的创建和相互之间的依赖关系写在配置文件中,也就是说bean及其之间的依赖关系反映在容器使用的配置元数据中,以此达到松耦合的效果。

DI即依赖注入,指的是组件以一些预先定义好的方式(如Setter 方法)接受来自于容器的资源注入。IoC也被称为是DI。

IoC is also known as dependency injection (DI). ---Spring5.1.3.RELEASE文档

AOP可以将与业务无关却被业务调用的逻辑封装起来,为应用业务做统一或特定的功能增强,能实现应用业务与增强逻辑的解耦,例如日志、事务等功能通过AOP实现。

Spring框架的核心模块:

2、Spring快速上手

2.1 创建工程

环境为:jdk1.8,maven 3.6.3,idea2021.1

创建一个maven工程

2.2 添加项目依赖信息

在项目的pom.xml中添加spring依赖信息,快速上手项目只需要导入context包,这里使用的是Spring的5.1.3.RELEASE:

代码语言:javascript
复制
<project ...>
...
    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.1.3.RELEASE</version>
        </dependency>
    </dependencies>
</project>

点击右上角的load maven changes按钮进行依赖安装

2.3 创建配置文件

在项目src/main/resources下创建spring配置文件

初始化配置:

代码语言:javascript
复制
<?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">

</beans>

配置idea的应用上下文,直接点ok

image-20210725221556129

2.4 创建实体类

在src/main/java下创建名为Person的实体类,可自定义包结构(我的为top.jtszt.bean),快速上手只是感受控制反转的效果,因此先不用在类中定义信息

2.5 声明bean

在Spring配置文件中加入对于Person类的声明,在beans标签体中使用bean标签声明:

代码语言:javascript
复制
<!-- id代表的是该bean的唯一标识 class为需要声明的类的全类名 -->
<beans...>
    <bean id="person" class="top.jtszt.bean.Person"></bean>
</beans>
2.6 创建启动类

在自定义包下创建一个启动类QuickStartApplication.java

代码语言:javascript
复制
public class QuickStartApplication {
    public static void main(String[] args) {
         ApplicationContext ioc =  new ClassPathXmlApplicationContext("ioc.xml");
        Person person = (Person) ioc.getBean("person");
        System.out.println(person);
    }
}

这里使用了ClassPathXmlApplicationContext来加载配置文件,加载完成后用ApplicationContext接口来接收,接着调用getBean方法,传入需要获取的bean的id,获取该bean并打印

代码语言:javascript
复制
top.jtszt.bean.Person@523884b2

至此就完成了Spring框架的快速上手,可以发现我们并没有手动去new对象,而是把对象声明在配置文件中,之后通过工厂获取出这个对象

3、IoC部分

3.1 IoC容器

org.springframework.context.ApplicationContext接口代表了Spring IoC容器,它负责实例化、配置、组装bean。通过快速上手了解到,可以将类的相关声明写在配置文件中,(此外还可以使用注解驱动开发,下面会细讲),之后将资源加载到IoC容器中,通过容器去管理。而在通过IoC容器读取Bean的实例之前,需要先将IoC容器本身实例化。在web应用中通常都是通过ClassPathXmlApplicationContext在classpath下加载配置文件(基于xml配置),生成一个IoC容器:

代码语言:javascript
复制
ApplicationContext ioc = new ClassPathXmlApplicationContext("ioc.xml");

实际上这里还可以返回成BeanFactory,这是IoC容器的基本实现,它的特点是延迟载入所有Bean;而ApplicationContext是BeanFactory的子接口,它简化了与 AOP 的整合、消息机制、事件机制,以及对 Web 环境的扩展,同时保持基本特性的兼容。Spring官方文档中推荐使用这种方式。

You should use an ApplicationContext unless you have a good reason for not doing so.

除此之外还可以通过FileSystemXmlApplicationContext从文件系统或者URL装载XML配置文件;XmlWebApplicationContextXmlPortletApplicationContext用于Web和入口应用程序。

3.2 依赖查找(基于xml)

依赖查找指的是容器中的受控对象通过容器的API来查找自己所依赖的资源和协作对象。通过这种方式来查找对象需要调用相关的api。上面使用到的 ioc.getBean("person")即是依赖查找。

1)基于上下文的依赖查找:

①通过对象的id获取,传入配置在xml文件中的对象的id,也就是快速上手的那种获取方法;

②通过对象类型去查找,需要注意的是,如果同一个类型的bean在XML文件中配置了多个,则获取时会抛出异常,所以同一个类型的bean在容器中必须是唯一的:

代码语言:javascript
复制
Person person = ioc.getBean(Person.class);

③通过使用类型和id参数搭配的方式查找

代码语言:javascript
复制
Person person = ioc.getBean("person", Person.class);

④通过getBeansOfType方法获取传入接口/抽象类的实现类/子类(假设MyInterface是接口)

代码语言:javascript
复制
Map<String, MyInterface> beans = ioc.getBeansOfType(MyInterface.class);
2)查找IoC容器所有bean

如果需要查找出IoC容器中的所有bean,还可以使用getBeanDefinitionNames方法,这个方法会获取所有bean的id,接着可以根据id去找出对应的bean

代码语言:javascript
复制
String[] beanNames = ioc.getBeanDefinitionNames();
3)延迟查找

对于一些特殊的场景,需要依赖容器中的某些特定的 Bean ,但当它们不存在时需要有方法去处理对应的情况,而不是抛异常。假设我们现在Person类没有在IoC容器中,那么如果直接getBean会报NoSuchBeanDefinitionException异常,我们需要的是让他延迟查找这个bean,怎么做?

ApplicationContext中有一个方法叫 getBeanProvider,传入bean的类信息,得到的是一个ObjectProvider<>对象,只有在调用该对象的getObject方法试图取出里面的bean对象时才会抛异常。

再进一步,如果bean不存在,我不想让它抛异常,怎么做?

ObjectProvider中还有一个方法叫getIfAvailable,在bean存在时会获取到bean,而获取bean失败时返回null而非异常。

3.3 依赖注入(基于xml)

现在我们已经可以从IoC容器中获取到对象了,但可以发现这些对象都是没有具体的属性的,而依赖注入是一个过程,也就是说对于这些属性我们不用自己手动去传,而是交给IoC容器去处理,让容器通过反射的方式去进行对象的注入。

对Person对象进行改造:

代码语言:javascript
复制
public class Person {
    private String name;
    private Integer age;
    private String phone;
    private Car car;
    private List<Car> CarList;
    private Map<String, Object> testMap;
    
    public Person(String name, Integer age, String phone) {
        this.name = name;
        this.age = age;
        this.phone = phone;
    }
    
    public void setTestMap(Map<String, Object> testMap) {
        this.testMap = testMap;
    }
    public void setCar(Car car) {this.car = car;}
    public void setCarList(List<Car> carList) {CarList = carList;}
    public void setnameForPerson(String name) {this.name = name;}
    public void setAge(Integer age) {this.age = age;}
    public void setPhone(String phone) {this.phone = phone;}
    //重写toString方法
}

依赖注入有两个主要的形式,一个是基于构造函数的依赖注入,一个是基于 Setter 的依赖注入。

1)基于Setter的依赖注入;

在xml文件中进行配置,使用property标签,name属性为对应的setXx方法的这个Xx,而不是在类中定义的属性,value为属性值:

代码语言:javascript
复制
<bean id="person1" class="top.jtszt.bean.Person">
    <!-- 可以看到这里写的是nameForPerson并非name -->
    <property name="nameForPerson" value="zhangsan"/>
    <property name="age" value="16"/>
    <property name="phone" value="135000"/>
</bean>
2)基于构造器的依赖注入;

在xml文件中,使用constructor-arg标签进行赋值,name为构造器参数名,value为值:

代码语言:javascript
复制
<bean id="person2" class="top.jtszt.bean.Person">
    <!-- 调用有参构造器进行创建对象并赋值 -->
    <constructor-arg name="name" value="lisi"/>
    <constructor-arg name="age" value="18"/>
    <constructor-arg name="phone" value="135111"/>
</bean>

这里也可以省略constructor-arg的name属性,但是必须按照构造器顺序写value

3)为bean属性赋值的其他情况

①为属性赋值null;

代码语言:javascript
复制
<bean id="person3" class="top.jtszt.bean.Person">
    <property name="name">
        <null/>
    </property>
</bean>

②为引用类型的属性赋值;

创建一个Car类:

代码语言:javascript
复制
public class Car {
    private String carName;
    private Integer price;

    public void setCarName(String carName) {this.carName = carName;}
    public void setPrice(Integer price) {this.price = price;}
    //重写toString
}

方式1:使用bean标签赋值

代码语言:javascript
复制
<bean id="person4" class="top.jtszt.bean.Person">
    <property name="car">
        <bean class="top.jtszt.bean.Car">
            <property name="carName" value="benz"/>
            <property name="price" value="8800"/>
        </bean>
    </property>
</bean>

方式2:引用外部bean

代码语言:javascript
复制
<bean id="car1" class="top.jtszt.bean.Car">
    <property name="carName" value="bmw"/>
    <property name="price" value="3380"/>
</bean>
<bean id="person4" class="top.jtszt.bean.Person">
    <property name="car" ref="car1"/>
</bean>

③为集合类型属性赋值;

1)为List属性赋值:

代码语言:javascript
复制
<bean id="person5" class="top.jtszt.bean.Person">
    <property name="carList">
        <!-- 这里的list标签相当于 list = new ArrayList<>(); -->
        <list>
        <!-- 方式一:直接写内部bean -->
            <bean class="top.jtszt.bean.Car">
                <property name="carName" value="byd"/>
                <property name="price" value="6600"/>
            </bean>
        <!-- 方法二:引用外部bean -->
            <ref bean="car1"/>
        <!-- list中还有value标签可以赋单值 -->
        </list>
    </property>
</bean>

2)为map属性赋值:

代码语言:javascript
复制
<bean id="person6" class="top.jtszt.bean.Person">    
    <property name="testMap">
        <!-- 1.map标签相当于 map = new LinkedHashMap<>(); -->
        <map>
            <!-- 方式一:在value中直接写值 -->
            <entry key="key01" value="zhangsan"/>
            <!-- 方式二:value是一个引用bean的内容 -->
            <entry key="key02" value-ref="car1"/>
            <!-- 方式三:在entry标签内部直接写bean去作为它的值 -->
            <entry key="key03">
                <bean class="top.jtszt.bean.Car">
                    <property name="carName" value="honda"/>
                    <property name="price" value="5200"/>
                </bean>
            </entry>
        </map>
    </property>
</bean>
3.4 注解驱动开发

从Spring Framework3.0之后引入了大量注解,可以使用注解驱动的方式来代替原来的xml配置,这也是后来比较常见的一种配置方式。

1)配置类

注解驱动需要的是配置类,一个配置类就可以理解为一个 xml ,只要在类上标注一个 @Configuration ,这个类即是配置类。而在xml中我们使用的是bean标签来声明bean,而在注解驱动中只需要在方法上标注@Bean即可代表bean的声明。

代码语言:javascript
复制
@Configuration
public class ConfClass {
    //默认方法名为bean的id,如果使用 @Bean("xx") 则代表xx为bean的id
    //返回值类型为bean的类型
    @Bean
    public Person person(){
        return new Person();
    }
}

这就相当于创建了一个xml文件,并在IoC容器中注册了id为person的Person类。

2)依赖查找

在完成配置类之后,依赖的查找需要用到AnnotationConfigApplicationContext来初始化加载容器。

代码语言:javascript
复制
ApplicationContext context = new AnnotationConfigApplicationContext(ConfClass.class);
Person person = (Person)context.getBean("person");
System.out.println(person);
3)依赖注入

方式一:基于Setter方法的注入

只需要在方法中使用set方法对属性进行赋值,将赋值属性之后的对象返回即可。

代码语言:javascript
复制
@Bean
public Person person(){
    Person person = new Person();
    person.setName("zs");
    person.setAge(11);
    return person;
}

方式二:基于构造函数的注入

代码语言:javascript
复制
@Bean
public Person person(){
    return new Person("zs",11,"135111");
}
4)组件注册

当我们需要注册的bean越来越多的时候,写很多方法标注很多的bean注解是不现实的。因此Spring中也提供了一些模式注解,可以实现对组件的快速注册。最基本的就是@Component注解,代表的是被注解的类会被注册到IoC容器中作为一个 Bean ,也就是说我们可以直接在Person实体类上标注该注解,那么就不用手动去写bean注解标注的方法进行注册。

代码语言:javascript
复制
@Component
public class Person {
    private String name;
    ....
}

这样配置之后默认是将Person类注册到IoC容器中,id为类名的小驼峰式,如果想指定id,可以使用 @Component("xx")声明。

5)组件扫描

在声明组件之后,还需要进行组件的扫描才能让IoC容器感知到组件的存在。我们可以直接在配置类上配置多一个@ComponentScan("xx")注解,xx为包路径,指定需要扫描的包及其子包。

代码语言:javascript
复制
@Configuration
@ComponentScan("top.jtszt.bean")
public class ConfClass { }

还可以在创建AnnotationConfigApplicationContext对象时传入包路径,这样也可以进行组件扫描。

代码语言:javascript
复制
ApplicationContext context = new AnnotationConfigApplicationContext("top.jtszt.bean");

除了使用注解驱动有组件扫描之外,基于xml配置也可以进行组件扫描

代码语言:javascript
复制
<beans>
    <context:component-scan base-package="top.jtszt.bean"/>
</beans>
6)声明bean的几个注解

@Component :通用的注解,可标注任意类为 Spring 组件。

@Repository : 对应持久层即 Dao 层,主要用于数据库相关操作。

@Service : 对应服务层,主要涉及一些复杂的逻辑,需要用到 Dao层。

@Controller : 对应 Spring MVC 控制层,主要用户接受用户请求并调用 Service 层返回数据。

7) 注解与xml梦幻联动

在xml中开启注解配置,并声明配置类

代码语言:javascript
复制
<beans>
    <context:annotation-config/>
    <bean class="top.jtszt.annotation.ConfClass"/>
</beans>

在配置类上使用注解@ImportResource引入xml文件

代码语言:javascript
复制
@Configuration
@ImportResource("classpath:applicationcontext.xml")
public class ConfClass { }
3.5 依赖注入的其他姿势(基于注解)
1)注解式属性注入

在对@Component扫描进去的组件进行属性注入时,可以使用@Value("xx")注解标在对应属性上对属性进行信息注入,并且该实体类可以不带Setter方法。

代码语言:javascript
复制
@Component
public class Person {
    @Value("zs")
    private String name;
    @Value("12")
    private Integer age;
    @Value("132111")
    private String phone;
    //重写toString
}
2)从外部配置文件注入

在Spring中从外部配置文件读取信息之后注入给属性也是被允许的。首先需要使用@PropertySource("xx")注解标注在类上,其中xx代表配置文件的位置。之后在属性上使用@Value("${yy}")注解进行注入,其中yy代表该值对应在配置文件中的key。

①在类路径下创建一个配置文件my.properties

代码语言:javascript
复制
person.name=ls
person.age=16
person.phone=135123

②在实体类上标注@PropertySource("classpath:my.properties")

③在对应属性上标注@Value进行取值

代码语言:javascript
复制
@Component
@PropertySource("classpath:my.properties")
public class Person {
    @Value("${person.name}")
    private String name;
    @Value("${person.age}")
    private Integer age;
    @Value("${person.phone}")
    private String phone;
    //重写toString
}
3)SpEL实现注入

SpEL也就是Spring表达式语言 ,它从Spring3.0开始被支持,SpEL支持调用属性值、属性参数以及方法调用、数组存储、逻辑计算等功能。SpEL 的语法统一用 #{xx} 表示,xx为表达式。

最常见的是使用SpEL对bean属性的引用或者方法的调用。

例:现在有两个实体类Bird与Dog,我们可以使用SpEL将Bird的age属性注入到Dog的age属性中。

代码语言:javascript
复制
@Component
public class Bird {
    @Value("16")
    private String age;
    ...
}
代码语言:javascript
复制
@Component
public class Dog {
    @Value("#{bird.age}")
    private String age;
    ...
}
3.6 自动注入
1)@Autowired

在 bean 中直接在属性或者Setter方法上标注 @Autowired 注解,IoC 容器会按照属性对应的类型,从容器中找对应类型的 bean 赋值到对应的属性上,实现自动注入。

如果容器中找不到对应类型的bean,那么会抛出NoSuchBeanDefinitionException异常,也可以在该注解上加上required = false ,那么找不到bean时会注入null。

假设有一个Car类,现在Person类有一个属性叫car,要对它实现自动注入:

代码语言:javascript
复制
@Component
public class Person {
    private String name;
    @Autowired
    private Car car;
    //重写toString
}

★Autowired注入的原理:

首先会拿到该属性的类型去IoC容器中找,如果找到一个则返回;如果找不到就抛异常(找不到bean);如果找到多个,那么会根据属性id去容器中找有没有对应的id,如果有就返回,没有就抛异常(该类型bean不唯一)。

2)@Qualifier

如果容器中存在多个类型相同的bean(且id不匹配)将会注入失败。这时可以使用@Qualifier注解显式地指定要注入哪一个bean。

代码语言:javascript
复制
@Autowired
@Qualifier("bmw")
private Car car;
3)@Primary

除了使用@Qualifier之外,还可以在被注入的 Bean 上标注@Primary,可以指定默认注入的Bean。

代码语言:javascript
复制
@Configuration
@ComponentScan("top.jtszt.bean")
public class ConfClass {
    @Bean
    @Primary
    public Car bmw(){
        return new Car();
    }
}
4)@Resource

@Resource 来自JSR250规范,它与 @Autowired 的不同之处在于:@Autowired 是按照类型注入,@Resource 是直接按照属性名 / Bean的名称注入,相当于@Autowired@Qualifier的结合。

代码语言:javascript
复制
@Resource(name="benz")
private Car carCar;
5)@Inject

@Inject来自JSR330规范,使用前需要导入javax.inject依赖。使用上等同于@Autowired,但由于它是JSR的规范,因此不受Spring框架的限制。

3.7 DI与DL的异同

作用目标不同•依赖注入的作用目标通常是类成员•依赖查找的作用目标可以是方法体内,也可以是方法体外 •实现方式不同•依赖注入通常借助一个上下文被动的接收•依赖查找通常主动使用上下文搜索

3.8 bean高级
1)bean的作用域

singleton:单实例的bean在容器创建好之前就已经完成创建,并且在容器中只有单一的对象;

prototype:多实例的bean只有在调用相关方法获取bean时才会被创建,并且获取一次创建一个;

request : 每一次HTTP请求都会产生一个新的bean,该bean仅在当前HTTP request内有效;

session : 每一次HTTP请求都会产生一个新的 bean,该bean仅在当前 HTTP session 内有效;

global-session: 全局session作用域,仅仅在基于portlet的web应用中才有意义,Spring5已经没有了。Portlet是能够生成语义代码(例如:HTML)片段的小型Java Web插件。它们基于portlet容器,可以像servlet一样处理HTTP请求。但是,与 servlet 不同,每个 portlet 都有不同的会话。

在bean的配置中可以通过scope属性指定单实例/多实例。

代码语言:javascript
复制
<!--bean的作用域默认是单实例(singleton) -->
<bean id="car1" class="top.jtszt.bean.Car" scope="prototype"/>
2)bean的类型

①普通bean

类似前面创建的那些bean都是普通bean

代码语言:javascript
复制
@Component
public class Person { ... }

②工厂bean

所谓工厂bean就是在bean对象创建过于复杂,或者有一些特殊策略时借助FactoryBean 使用工厂方法来创建bean。FactoryBean 接口是一个创建对象的工厂,如果 Bean 实现了 FactoryBean 接口,则它本身将不再是一个普通的 Bean ,不会在实际的业务逻辑中起作用,而是由创建的对象来起作用。

FactoryBean接口有三个方法:

代码语言:javascript
复制
public interface FactoryBean<T> {
    // 返回创建的对象
    @Nullable
    T getObject() throws Exception;
    
    // 返回创建的对象的类型(即泛型类型)
    @Nullable
    Class<?> getObjectType();

    // 创建的对象是单实例Bean还是原型Bean,默认单实例
    default boolean isSingleton() {
        return true;
    }
}

★关于FactoryBean的几个注意点:

•它创建的bean直接放在 IoC 容器中•它的加载是伴随IoC容器的初始化时机一起的,也就是在容器生成好之前就创建•它生产bean的机制是延迟生产,只有调用方法获取bean时才会创建•使用它生产出来的bean默认是单实例的

★BeanFactory 和FactoryBean 的区别:

BeanFactory:从类的继承结构上看,它是实现Spring最顶层的容器实现;从类的组合结构上看,它是最深层次的容器,ApplicationContext 在最底层组合了 BeanFactory 。

FactoryBean :创建对象的工厂 bean ,可以使用它来直接创建一些初始化流程比较复杂的对象。

3)bean的生命周期

•Bean 容器找到配置文件中 Spring Bean 的定义。 •Bean 容器利用 Java Reflection API 创建一个Bean的实例。 •如果涉及到一些属性值 利用 set()方法设置一些属性值。 •如果 Bean 实现了 BeanNameAware 接口,调用 setBeanName()方法,传入Bean的名字。 •如果 Bean 实现了 BeanClassLoaderAware 接口,调用 setBeanClassLoader()方法,传入 ClassLoader对象的实例。 •与上面的类似,如果实现了其他 *.Aware接口,就调用相应的方法。 •如果有和加载这个 Bean 的 Spring 容器相关的 BeanPostProcessor 对象,执行postProcessBeforeInitialization() 方法 •如果Bean实现了InitializingBean接口,执行afterPropertiesSet()方法。 •如果 Bean 在配置文件中的定义包含 init-method 属性,执行指定的方法。 •如果有和加载这个 Bean的 Spring 容器相关的 BeanPostProcessor 对象,执行postProcessAfterInitialization() 方法 •当要销毁 Bean 的时候,如果 Bean 实现了 DisposableBean 接口,执行 destroy() 方法。 •当要销毁 Bean 的时候,如果 Bean 在配置文件中的定义包含 destroy-method 属性,执行指定的方法。引用[1]

4)bean的实例化方式

①直接通过 <bean>标签 或者 @Bean@Component注解 注册 bean 后实例化

②借助 FactoryBean 实例化 bean

③使用静态工厂方法 factory-method实例化 bean

④使用实例工厂方法factory-bean + factory-method 实例化 bean

5)单实例bean的线程安全问题

默认情况下单实例 bean 的线程是不安全的( 只要有可能变动的成员属性 ),也就是说如果在单实例bean的全局层面上定义有数据存储功能的对象 / 基本类型变量 / static变量,那么就会存在线程不安全的问题。

解决方法:

•通过声明Bean的 Scope="prototype",将bean变成多实例

•使用本地变量 ThreadLocal 进行定义


参考资料:

•Spring Framework 5.1.3.RELEASE文档[2]•从 0 开始深入学习 Spring-掘金小册[3]•JavaGuide-Spring[4]•Spring中单例Bean的线程安全问题-CSDN[5]•Spring Bean的生命周期-博客园[6]•Spring IOC 容器源码分析_Javadoop[7]•Spring5 系统架构-CSDN[8]•雷丰阳Spring、Spring MVC、MyBatis课程-bilibili[9]

相关链接

[1] 引用: https://snailclimb.gitee.io/javaguide-interview/#/./docs/e-1spring?id=spring-%e4%b8%ad%e7%9a%84-bean-%e7%94%9f%e5%91%bd%e5%91%a8%e6%9c%9f [2] Spring Framework 5.1.3.RELEASE文档: https://docs.spring.io/spring-framework/docs/5.1.3.RELEASE/spring-framework-reference/ [3] 从 0 开始深入学习 Spring-掘金小册: https://juejin.cn/book/6857911863016390663/section [4] JavaGuide-Spring: https://snailclimb.gitee.io/javaguide-interview/#/./docs/e-1spring [5] Spring中单例Bean的线程安全问题-CSDN: https://blog.csdn.net/vipshop_fin_dev/article/details/109017732 [6] Spring Bean的生命周期-博客园: https://www.cnblogs.com/zrtqsk/p/3735273.html [7] Spring IOC 容器源码分析_Javadoop: https://javadoop.com/post/spring-ioc [8] Spring5 系统架构-CSDN: https://blog.csdn.net/lj1314ailj/article/details/80118372 [9] 雷丰阳Spring、Spring MVC、MyBatis课程-bilibili: https://www.bilibili.com/video/BV1d4411g7tv?p=256

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-07-30,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Java后端修炼 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1、概述
  • 2、Spring快速上手
    • 2.1 创建工程
      • 2.2 添加项目依赖信息
        • 2.3 创建配置文件
          • 2.4 创建实体类
            • 2.5 声明bean
              • 2.6 创建启动类
              • 3、IoC部分
                • 3.1 IoC容器
                  • 3.2 依赖查找(基于xml)
                    • 1)基于上下文的依赖查找:
                      • 2)查找IoC容器所有bean
                        • 3)延迟查找
                          • 3.3 依赖注入(基于xml)
                            • 1)基于Setter的依赖注入;
                              • 2)基于构造器的依赖注入;
                                • 3)为bean属性赋值的其他情况
                                  • 3.4 注解驱动开发
                                    • 1)配置类
                                      • 2)依赖查找
                                        • 3)依赖注入
                                          • 4)组件注册
                                            • 5)组件扫描
                                              • 6)声明bean的几个注解
                                                • 7) 注解与xml梦幻联动
                                                  • 3.5 依赖注入的其他姿势(基于注解)
                                                    • 1)注解式属性注入
                                                      • 2)从外部配置文件注入
                                                        • 3)SpEL实现注入
                                                          • 3.6 自动注入
                                                            • 1)@Autowired
                                                              • 2)@Qualifier
                                                                • 3)@Primary
                                                                  • 4)@Resource
                                                                    • 5)@Inject
                                                                      • 3.7 DI与DL的异同
                                                                        • 3.8 bean高级
                                                                          • 1)bean的作用域
                                                                            • 2)bean的类型
                                                                              • 3)bean的生命周期
                                                                                • 4)bean的实例化方式
                                                                                  • 5)单实例bean的线程安全问题
                                                                                  • 相关链接
                                                                                  相关产品与服务
                                                                                  容器服务
                                                                                  腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
                                                                                  领券
                                                                                  问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档