Spring中的@Bean注解

前言

Spring中最重要的概念IOC和AOP,实际围绕的就是Bean的生成与使用。

关于IOC注解分为两类:

1、一类是使用Bean,即是把已经在xml文件中配置好的Bean拿来用,完成属性、方法的组装;比如@Autowired , @Resource,可以通过byTYPE(@Autowired)、byNAME(@Resource)的方式获取Bean;

2、一类是注册Bean,@Component , @Repository , @ Controller , @Service , @Configration这些注解都是把你要实例化的对象转化成一个Bean,放在IoC容器中,等你要用的时候,它会和上面的@Autowired , @Resource配合到一起,把对象、属性、方法完美组装。

@Bean注解

Spring的@Bean注解用于告诉方法,产生一个Bean对象,然后这个Bean对象交给Spring管理。产生这个Bean对象的方法Spring只会调用一次,随后这个Spring将会将这个Bean对象放在自己的IOC容器中。默认添加的Bean的类型是方法的返回值,id是方法的名字。

实体类:

public class Person {
    private String name;
    private Integer age;

    public Person() {
    }

    public Person(String name, Integer age) {
    this.name = name;
    this.age = age;
    }
    
    public void init() {
        System.out.println("init ............");
    }
    
    public void destroy() {
        System.out.println(" destroy ...............");
    }

    // 省略 getter setter 方法

    // 省略 toString 方法
}

JavaConfig配置类:

@Configuration
public class MyConfig {

    @Bean
    public Person person() {
        return new Person("czx", 23);
    }

}

测试代码:

@Test
public void test() {
    ApplicationContext ctx = new AnnotationConfigApplicationContext(BeanConfig.class);
    Person person = ctx.getBean(Person.class);
    System.out.println(person);
}

输出结果:

Person{name='czx', age='23'}

@Bean 注解的属性

属性作用
value为bean起一个名字 默认方法的名字(同name)
name为bean起一个名字 默认方法的名字(同value)
autowire是否对该bean的属性实行自动装配
initMethod初始化方法
destroyMethod销毁方法

autowire属性的三种取值:
Autowire.NO (默认设置)
Autowire.BY_NAME
Autowire.BY_TYPE
指定 bean 的装配方式, 根据名称 和 根据类型 装配, 一般不设置,采用默认即可。

initMethod属性和destroyMethod的使用:

@Configuration
public class BeanConfig {

    @Bean(initMethod = "init",destroyMethod = "destroy")
    public Person person() {
        return new Person("czx", 23);
    }
}

如果 bean 是单例:在IoC容器启动时创建 bean 对象调用 bean 的初始化方法, 直接指定方法名称即可,不用带括号。bean 的销毁方法, 在调用 IoC 容器的 close() 方法时,会执行到该属性指定的方法。

如果 bean 是多例:在IoC容器启动时不创建 bean 对象,在使用时才创建bean 对象调用 bean 的初始化方法,并且IoC 容器不再会管理 bean 的声明周期,不会在调用 bean 的销毁方法。

通过上述方法创建的bean是单例的。可以使用@Scope注解改变bean的声明周期。

@Scope注解

@Scope注解是Ioc容器中的一个作用域,在 Spring IoC 容器中具有以下几种作用域:基本作用域singleton(单例)、prototype(多例),Web 作用域(reqeust、session、globalsession)。@scope默认是单例模式。

  1. singleton(单例 ): 全局有且仅有一个实例。
  2. prototype(多例): 每次获取Bean的时候会有一个新的实例。
  3. request : request表示该针对每一次HTTP请求都会产生一个新的bean,同时该bean仅在当前HTTP request内有效。
  4. session :session作用域表示该针对每一次HTTP请求都会产生一个新的bean,同时该bean仅在当前HTTP session内有效。
  5. globalsession : global session作用域类似于标准的HTTP Session作用域,不过它仅仅在基于portlet的web应用中才有意义。

单例JavaConfig配置类:

@Configuration
public class MyConfig {

    @Bean
    @Scope(value="singleton")
    public Person person() {
        return new Person("czx", 23);
    }

}

单例测试类:

@Test
public void test() {
    ApplicationContext ctx = new AnnotationConfigApplicationContext(BeanConfig.class);
    Person person1 = ctx.getBean(Person.class);
    Person person2 = ctx.getBean(Person.class);
    System.out.println(person1 == person2);
}

单例结果:

true

多例JavaConfig配置类:

@Configuration
public class MyConfig {

    @Bean
    @Scope(value="prototype")
    public Person person() {
        return new Person("czx", 23);
    }

}

多例测试类:

@Test
public void test() {
    ApplicationContext ctx = new AnnotationConfigApplicationContext(BeanConfig.class);
    Person person1 = ctx.getBean(Person.class);
    Person person2 = ctx.getBean(Person.class);
    System.out.println(person1 == person2);
}

多例结果:

false

Spring默认的类型也是singleton,singleton虽然保证了全局是一个实例,对性能有所提高,但是如果实例中有非静态变量时,会导致线程安全问题,共享资源的竞争。当设置为prototype时每次连接请求,都会生成一个bean实例,也会导致一个问题,当请求数越多,性能会降低。

单例在IoC容器启动时就创建bean对象,如果想像多例一样在使用的时候再创建bean对象能办到吗?我们可以使用@Lazy注解实现懒加载。

@Lazy注解

懒加载只针对单实例bean,对于单实例bean默认在容器启动的时候创建对象。标注@Lazy后,容器启动不创建对象。第一次使用(获取)Bean创建对象,并初始化;

@Configuration
public class MyConfig {

    @Bean
    @Scope
    @Lazy
    public Person person() {
        return new Person("czx", 23);
    }

}

在使用@Bean注解的同时也经常使用@Value注解,如果想了解请自行跳转。ω

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值