Spring第三篇-@Configuration和@Bean,@Configuration加不加到底区别在哪

@Configuration注解

@Configuration这个注解可以加在类上,让这个类的功能等同于一个bean xml配置文件。

@Configuration
public class TestBean{

}

效果等同于

<?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-4.3.xsd">

</beans>

@Configuration 使用步骤:

  1. 在类上使用 @Configuration 注解
  2. 通过 AnnotationConfigApplicationContext 容器来加载 @Configuration 注解修饰的类

@Bean注解

用法:
这个注解类似于bean xml配置文件中的bean元素,用来在spring容器中注册一个bean。
@Bean注解用在方法上,表示通过方法来定义一个bean,默认将方法名称作为bean名称,将方法返回
值作为bean对象,注册到spring容器中。

@Bean
public User user1() {
return new User();
}

看一@Bean的源码:

@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Bean {
@AliasFor("name")
String[] value() default {};
@AliasFor("value")
String[] name() default {};
@Deprecated
Autowire autowire() default Autowire.NO;
boolean autowireCandidate() default true;
String initMethod() default "";
String destroyMethod() default AbstractBeanDefinition.INFER_METHOD;
}

@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})说明这个注解可以用在方法和注解类型上面
每个参数含义:

  1. value和name是一样的,设置的时候,这2个参数只能选一个,原因是@AliasFor导致的
    @AliasFor这个注解不清楚的可以看这个文章:(文章最后)

https://blog.csdn.net/whatname123/article/details/107721423

  1. value:字符串数组,第一个值作为bean的名称,其他值作为bean的别名
  2. autowire:这个参数上面标注了@Deprecated,表示已经过期了,不建议使用了
  3. autowireCandidate:是否作为其他对象注入时候的候选bean。有多个同类型的bean,在spring不知道选哪个的时候起作用。
  4. initMethod:bean初始化的方法,这个和生命周期有关,这里先不讲
  5. destroyMethod:bean销毁的方法,也是和生命周期相关的,先不讲

使用:

class User {

}

@Configuration
public class BeanConfig {
//bean名称为方法默认值:user1
    @Bean
    public User user1(){
        return new User();
    }
//bean名称通过value指定了:userBean
    @Bean("userBean")
    public User user2(){
        return new User();
    }
//bean名称为:userBean1,2个别名:[testBean,myBean]
    @Bean({"userBean1","testBean","myBean"})
    public User user3(){
        return new User();
    }
}

输出(只截取了部分):

bean名称:beanConfig,别名:[],bean对象:com.test.annotation.BeanConfig$$EnhancerBySpringCGLIB$$9d7e12be@587c290d
bean名称:user1,别名:[],bean对象:com.test.annotation.User@4516af24
bean名称:userBean,别名:[],bean对象:com.test.annotation.User@4ae82894
bean名称:userBean1,别名:[myBean, testBean],bean对象:com.test.annotation.User@543788f3

去掉@Configuration会怎么样?

我们在BeanConfig类中去掉@Configuration
测试输出:

bean名称:beanConfig,别名:[],bean对象:com.test.annotation.BeanConfig@5e853265
bean名称:user1,别名:[],bean对象:com.test.annotation.User@67205a84
bean名称:userBean,别名:[],bean对象:com.test.annotation.User@7d0587f1
bean名称:userBean1,别名:[myBean, testBean],bean对象:com.test.annotation.User@5d76b067

对比上面的输出得出结论:

  1. 对比最后3行,可以看出:有没有@Configuration注解,@Bean都会起效,都会将@Bean修饰的方法作为bean注册到容器中
  2. 两个内容的第一行有点不一样,被@Configuration修饰的bean最后输出的时候带有
    EnhancerBySpringCGLIB 的字样,而没有@Configuration注解的bean没有Cglib的字样;有EnhancerBySpringCGLIB 字样的说明这个bean被cglib处理过的,变成了一个代理对象。
    关于cglib不清楚的请看这篇文章

https://blog.csdn.net/whatname123/article/details/115578231

@Configuration加不加到底区别在哪?

通常情况下,bean之间是有依赖关系的,我们来创建个有依赖关系的bean,通过这个案例你就可以看出根本的区别了。

案例一:(不加@Configuration)

package com.test.annotation;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

class User {

}
class People{
    private User user;

    public People(User user) {
        this.user = user;
    }
    @Override
    public String toString() {
        return "People{" +
                "user=" + user +
                '}';
    }
}


public class BeanConfig {
    @Bean
    public User user1(){
        System.out.println("调用了user创建方法");
        return new User();
    }
    @Bean
    public People people1(){
        User user = this.user1();
        System.out.println("调用了people创建方法一");
        return new People(user);
    }
    @Bean
    public People people2(){
        User user = this.user1();
        System.out.println("调用了people创建方法二");
        return new People(user);
    }
}

测试类还是用上面的测试类就行。
输出结果(截取部分):

调用了user创建方法
调用了user创建方法
调用了people创建方法一
调用了user创建方法
调用了people创建方法二
bean名称:user1,别名:[],bean对象:com.test.annotation.User@7d0587f1
bean名称:people1,别名:[],bean对象:People{user=com.test.annotation.User@5d76b067}
bean名称:people2,别名:[],bean对象:People{user=com.test.annotation.User@2a17b7b6}

加上@Configuration后
输出结果(截取部分):

调用了user创建方法
调用了people创建方法一
调用了people创建方法二
bean名称:user1,别名:[],bean对象:com.test.annotation.User@4ae82894
bean名称:people1,别名:[],bean对象:People{user=com.test.annotation.User@4ae82894}
bean名称:people2,别名:[],bean对象:People{user=com.test.annotation.User@4ae82894}

通过对比可以看出:

  1. 有@Configuration的,被@Bean修饰的方法都只被调用了一次。
  2. 有@Configuration的,所有的User都是同一个

这是为什么?
被@Configuration修饰的类,spring容器中会通过cglib给这个类创建一个代理,代理会拦截所有被@Bean 修饰的方法,默认情况(bean为单例)下确保这些方法只被调用一次,从而确保这些bean是同一个bean,即单例的
@Configuration修饰的类有cglib代理效果,默认添加的bean都为单例

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

静安书以沫

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

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

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

打赏作者

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

抵扣说明:

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

余额充值