Spring笔记

Spring学习笔记

前言

1. IoC(控制反转)

IoC是面向对象编程中的一种设计原则,可以用来减少代码之间的耦合。实现了IoC思想的容器成为IoC容器。

  • 在没有引入IoC容器前, 对象A依赖对象B,那么A对象在实例化或者运行到某一点时,自己必须主动创建对象B或者使用已经创建好的对象B。
  • 而在引入IoC容器后,对象A和对象B之间失去了直接联系,当对象A需要使用到对象B时,IoC容器会自动创建一个对象B注入到对象A所需要的地方。

通过上面的对比,可以看出对象A获得依赖对象B的过程,由主动变成了被动,即将创建对象的操作交给了IoC容器,控制权颠倒了过来,这就叫控制反转。

2.DI(依赖注入)

DI是实现IoC的方法之一,所谓依赖注入,就是IoC容器在运行期间,动态地将某种依赖关系注入到对象当中

3.IoC的优点

代码解耦、提高灵活性、可扩展性和可维护性

一、初始化/注册Bean

1.类注解

在类上使用注解@Controller@Service@Repository@Component。需要保证该类会被Spring扫描到,这种配置方式默认会注册一个名称为类名首字母小写的Bean对象到容器中。

package org.example.test;

import org.springframework.stereotype.Repository;

@Repository
public class Login {
}

定义好Bean对象并注册到容器中后就可以获取Bean对象了,获取Bean对象有两种方式:

  • 通过类型获取:这种获取方式要求该类型的Bean只有一个
  • 通过名称获取:同意类型的Bean可以有多个
package org.example.test;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Operation {
    public static void main(String[] args) {
        //根据Spring配置文件路径创建容器:应用上下文对象
        ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
        //获取Bean的两种方式
        Login login = (Login) context.getBean("login");  //通过名称获取,注意小写
        Login login2 = context.getBean(Login.class);  //通过类型获取
        System.out.println(login);  
        System.out.println(login2);  
    }
}
/*获取到的是同一个对象
org.example.test.Login@21a947fe
org.example.test.Login@21a947fe
*/
2.@Bean

当前类被Spring扫描到时,可以在方法上使用@Bean注解,通过方法返回类型,也可以定义、注册Bean对象,默认使用方法名作为Bean的名称

package org.example.test;

import lombok.Getter;
import lombok.Setter;
import lombok.ToString;

@ToString
@Getter
@Setter
public class Person {
    private String name;
    private int age;
}

使用注解@Bean来注册Bean对象,注意该方法的类必须被Spring扫描到

package org.example.test;

import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Controller;

@Controller  //对该类使用类注解
public class usePerson {
    @Bean  //注册Bean对象
    public Person person1(){
        Person person = new Person();
        person.setAge(23);
        person.setName("张三");
        return person;
    }

    @Bean
    public Person person2() {
        Person person = new Person();
        person.setName("李四");
        person.setAge(15);
        return person;
    }
}

使用Bean对象,默认使用方法的名称作为Bean的名称

        Person person1 = (Person) context.getBean("person1");
        Person person2 = (Person) context.getBean("person2");

        System.out.println(person1);
        System.out.println(person2);
/*
Person(name=张三, age=23)
Person(name=李四, age=15)
*/
3.@Configuration

当类被Spring扫描到时,使用@Configuration注解,可以注册一个配置类到容器中。配置类一般用来自定义配置某些资源。

4.FactoryBean接口

实现了FactoryBean接口的Bean,根据该Bean的ID从容器中获取的实际上是FactoryBean的getObject()返回的对象,而不是FactoryBean本身,如果要获取FactoryBean对象,在ID前加上&符号来获取

FactoryBean接口的实现方式:

public interface FactoryBean<T> {
    //返回的对象实例
    T getObject() throws Exception;
    
    //Bean的类型
    Class<?> getObjectType();
    
    //是否是单例的Bean对象,不实现该接口方法默认为单例
    default boolean isSingleton() {
        return true;
    }
}

实现FactoryBean接口,指定泛型类型为Person类,将getObject方法的返回对象注册到容器中

@Component
public class UseFactoryBean implements FactoryBean<Person> {
    @Override
    public Person getObject() throws Exception {
        Person p = new Person();
        p.setName("老王");
        p.setAge(52);
        return p;
    }

    @Override
    public Class<?> getObjectType() {
        return Person.class;
    }
}
        Person useFactoryBean = (Person) context.getBean("useFactoryBean");  //之前已经定义过Person对象,所以只能通过ID获取
        System.out.println(useFactoryBean);

二、依赖注入

1.属性注入

当前类被Spring扫描到时,可以在属性上使用@Autowired注解,会将容器中的Bean对象装配进来。

package org.example.test;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

@Repository
public class Login {
    @Autowired
    private Person person;
}

在setter方法上使用@Autowired注入

package org.example.test;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class LoginBySetter {
    private Person person;

    public Person getPerson() {
        return this.person;
    }
    
    @Autowired  //在构造方法上加@Autowired
    public void setPerson(Person person) {
        System.out.println("LoginBySetter: Person = " + person);
        this.person = person;
    }
}

2.构造方法注入

当前类被Spring扫描到时,可以在构造方法上使用@Autowired注解,作用和setter方法类似,会将容器中的Bean对象注入方法参数。

@Repository
public class Login {

    private Person person;
    
    @Autowired
    public Login(Person person) {
        this.person = person;
    }
}

在使用@Bean注解的方法上,容器中的Bean会自动注入参数

    @Bean
  public Person person3(Login login){
    System.out.printf("person3: %s%n", login == this.login);    
   	Person person = new Person();
    person.setAge(33);
    person.setName("小马");
    return person;
  }
3.注入指定的Bean:@Qualifier

同类型的Bean有多个时,注入该类型Bean需要指定Bean的名称:

  • 属性名或方法参数名设置为Bean的名称
  • 属性名或犯法参数设置@Qualifier("名称")注解,注解内的字符串是Bean对象的名称

三、Bean的作用域

Spring容器在初始化一个Bean的实例时,同时会指定该实例的作用域。Spring有6个作用域,最后四种基于Spring WebMVC生效:

singleton

该作用域下的Bean在IoC容器中只有一个实例:获取Bean及装配Bean都是同一个对象。通常无状态的Bean使用该作用域,无状态表示Bean对象的属性不需要更新。Spring默认选择该域

prototype

每次对该作用域下的Bean的请求都会创建新的实例:获取Bean及装配Bean都是新的对象实例。通常有状态的Bean 使用该作用域

request

每次http请求会创建新的Bean实例,类似于prototype。一次http的请求和响应的共享Bean

session

在一个http session中,定义一个Bean实例。用户会话的共享Bean,如:记录一个用户的登录信息。

application

在一个http servlet Context 中,定义一个Bean实例。Web应用的上下文信息,如:记录一个应用的共享信息

websocket

在一个http WebSocket的生命周期中,定义一个Bean 实例。WebSocket的每次会话中,保存了一个Map结构的头信息,将用来包裹客户端消息头。第一次初始化后,直到WebSocket结束都是同一个Bean。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值