当前位置:   article > 正文

Spring学习02-[Spring容器核心技术IOC学习]

Spring学习02-[Spring容器核心技术IOC学习]

什么是bean?

被Spring管理的对象就是bean,和普通对象的区别就是里面bean对象里面的属性也被注入了。

如何配置bean?

@Component方式、@bean配合配置类的方式、@import导入方式、类实现importSelect的方式

@Component方式

在需要被注册成bean的类上加上这个注解就可以了,只要spring能够扫描到,配置了@Component的类会被注册成bean

@Component的扩展注解还有@Service、@Repository

@bean配合配置类的方式

在这里插入图片描述
@bean写在方法上面并且结合配置类

@Configuration
@ComponentScan
public class SpringConfig {
    @Bean
    public User user(){
        return new User();
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

特别注意@bean底层会走cglib动态代理进行增强,代理逻辑就是先从spring容器中去找,如果没找到才会创建bean,找到了直接返回,目的是防止多例bean

  • 测试类
 @org.junit.Test
    public void test(){
        //要依赖spring注入,就需要从spring容器中获取UserService
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);
        User user = (User) context.getBean("user");
        System.out.println(user);
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

在这里插入图片描述

@import导入方式

@import注解导入的类会被spring注册成一个bean,一般这个注解放在配置类上,但是也可以放在其他ben类上

@Configuration
@ComponentScan
@Import(User.class)
public class SpringConfig {

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 测试
 @org.junit.Test
    public void test(){
        //要依赖spring注入,就需要从spring容器中获取UserService
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);
        User user = (User) context.getBean(User.class);
        System.out.println(user);
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

实现ImportSelector类的方式-批量注册bean

一般配合@import注解使用

@Import(实现ImportSelector.class)

  • 实现了ImportSelector的类
    重写selectImports方法,返回一个字符串数组,里面的内容就是要注册成bean的类的路径全限定名

可以批量注册bean(通过实现selectImports,返回bean的完整类路径字符串数组)

public class UserImportSelect implements ImportSelector {

    public String[] selectImports(AnnotationMetadata importingClassMetadata) {
        return new String[]{"com.spring.bean.User"};
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 配合@import
@Configuration
@ComponentScan
@Import(UserImportSelect.class)
public class SpringConfig {

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 测试
 @org.junit.Test
    public void test(){
        //要依赖spring注入,就需要从spring容器中获取UserService
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);
        User user = (User) context.getBean(User.class);
        System.out.println(user);
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

实现ImportBeanDefinitionRegistrar的方式

调用BeanDefinition注册器,手动注册一个bean

一般也是配合@import注解使用

public class UserImportSelect implements ImportBeanDefinitionRegistrar {

    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry, BeanNameGenerator importBeanNameGenerator) {
        //调用BeanDefinition注册器,手动注册一个bean

        RootBeanDefinition beanDefinition=new RootBeanDefinition();
        beanDefinition.setBeanClassName("com.spring.bean.User");

        registry.registerBeanDefinition("user",beanDefinition);
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 配合@import注解
@Configuration
@ComponentScan
@Import(UserImportSelect.class)
public class SpringConfig {

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 测试
 @org.junit.Test
    public void test(){
        //要依赖spring注入,就需要从spring容器中获取UserService
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);
        User user = (User) context.getBean(User.class);
        System.out.println(user);
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

实例化bean

Spring在实例化bean的时候,当扫描某个类发现有@component或者其他注解的时候,会调用这个类的无参构造函数,从而实例化bean

推断构造函数

规则:

  • 默认使用无参构造函数
  • 无参构造函数和有参构造函数同时存在,也会默认调用无参构造函数
  • 如果只有一个有参构造函数,spring会用有参构造函数,同时会将有参构造函数的参数实例化bean(有的时候会造成循环依赖问题)
  • 如果有多个有参构造函数,spring就不知道调用哪个了,必须指定默认的构造函数。指定方法就是方法上添加@Autowired注解,如下所示
@Data
public class User {
    private Integer id;
    private String name;

    private Person person;

    private UserService userService;

    public User(Person person) {
        System.out.println("创建user的构造函数");
        this.person = person;
    }

    //指定默认的构造函数
    @Autowired
    public User(Person person, UserService userService) {
        this.person = person;
        this.userService = userService;
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

使用实例工厂方法实例化----@Bean的方式

可以自由的选择构造函数进行实例化

使用工厂Bean。实例化-----FactoryBean

  • FactoryBean是一个接口

  • 需要有一个Bean,一旦这个Bean实现FactoryBean就成为了特殊的Bean
    在这里插入图片描述

  • 可以自由的选择构造函数进行实例化
    特殊 就是根据bean的名字实际上是获取getObject返回的对象(狸猫换太子)

  • 实现FactoryBean的方法

@Data
@Component
public class User implements FactoryBean<Person> {
    private Integer id;
    private String name;

    //特殊 就是根据bean的名字实际上是获取getObject返回的对象(狸猫换太子)
    public Person getObject() throws Exception {
        return new Person();
    }

    public Class<?> getObjectType() {
        return null;
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 测试
 @org.junit.Test
    public void test(){
        //要依赖spring注入,就需要从spring容器中获取UserService
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);
        System.out.println(context.getBean("user"));
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

可以看到返回的bean是getobject方法返回实例化bean
在这里插入图片描述

依赖注入(DI)

@Autowired

要实现依赖注入一定要使用@Autowired?
1、@Bean方法的参数会自动注入
2、构造函数的参数也会自动注入

  • 特性:
  • 可以写在方法、构造函数、字段
    1、写在构造函数(一般是多个有参构造函数,用@Autowired加在构造函数上来指定默认的构造函数)
    2、写在字段:表示依赖注入
    3、写在方法:方法里的参数会自动注入
  • 先byType后byName
    在这里插入图片描述
    在这里插入图片描述

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/秋刀鱼在做梦/article/detail/774014
推荐阅读
相关标签
  

闽ICP备14008679号