Spring中@Bean 与 @Autowired 的使用(部分复习)

 

@Bean 修饰的方法表示初始化一个对象并交由Spring IOC去管理,@Bean 只能和@Component @Repository @Controller @Service @Configration 配合使用.

@Autowired 可修饰变量和方法,用于完成自动装配(将需要的外部资源注入)

接下来看一段简单代码

 


下面的代码包括三个POJO(ADemo,BDemo,CDemo)和一个Bean配置方法(Beans)以及一个用来测试注入的BeanDemo



@Data
public class ADemo {

    private String id;

    private String name;
}

@Data
public class BDemo {

    private String id;

    private String name;
}

@Data
public class CDemo {

    private String id;

    private String name;
}



@Component
public class Beans {

    /*
    等同如下配置
        <bean id="aDemoTest" class="demo.Bean.ADemo">
        <property name="id" value="0719"></property>
        <property name="name" value="ADemo.Name"></property>
        </bean>
     */
    @Bean
    public ADemo aDemoTest(){
        ADemo aDemo=new ADemo();
        aDemo.setId("0719");
        aDemo.setName("ADemo.Name");
        return aDemo;
    }

    @Bean
    public BDemo bDemoTest(){
        BDemo bDemo=new BDemo();
        bDemo.setId("0719_1");
        bDemo.setName("BDemo.Name");
        return bDemo;
    }

    @Bean
    public CDemo cDemoTest(BDemo bDemo){
        CDemo cDemo=new CDemo();
        cDemo.setId(bDemo.getId());
        cDemo.setName(bDemo.getName());
        return cDemo;
    }

}


@Component
public class BeanDemo {


    private BDemo bDemo;

    private CDemo cDemo;

    //注释掉会抛出空指针异常
    @Autowired
    private void setBDemo(BDemo bDemo){
        //可以看出单例线程不安全
        bDemo.setName("set方法上添加@Autowired时修改了Name属性");
        this.bDemo=bDemo;
    }

    @Autowired
    private void initCDemo(CDemo cDemo){//无论方法名是set还是init或者其他,@Autowired都会检测bean并自动注入
        this.cDemo=cDemo;
    }

    public BDemo getbDemo() {
        return bDemo;
    }

    public CDemo getcDemo(){
        return cDemo;
    }

}

Beans里声明了三个对象的初始化内容,如果换成XML配置,则等同于

<bean id="aDemoTest" class="demo.Bean.ADemo">
        <property name="id" value="0719"></property>
        <property name="name" value="ADemo.Name"></property>
</bean>

非常普通的将两个属性赋值.

其中ADemo和BDemo都是如此,而CDemo则引入了BDemo对象,从BDemo中的值中获取内容,赋值给CDemo.

从这里可以看出,@Bean注释的方法可以采用任何必要的java功能来产生bean实例,简言之,只有被@Bean注释了,Spring会尽可能的去生成这个bean,为什么是尽可能而不是必须呢?假设A对象依赖B,B对象依赖C,C对象又回过头依赖A,则会抛出异常.当然这里只是举个简单例子.

接下来看看调用方法

@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
@ContextConfiguration(classes={SpringConfig.class})
public class MyTest {

    @Autowired
    private ADemo aDemo;

    @Autowired
    private BeanDemo beanDemo;

    @Autowired
    private CDemo cDemo;


    @Test
    public void showBean(){
        System.out.println(aDemo.toString());
        System.out.println(beanDemo.getbDemo().toString());
        System.out.println(beanDemo.getcDemo().toString());
        System.out.println(cDemo.toString());
    }
}

运行该测试方法后得到的结果如下

ADemo(id=0719, name=ADemo.Name)
BDemo(id=0719_1, name=set方法上添加@Autowired时修改了Name属性)
CDemo(id=0719_1, name=set方法上添加@Autowired时修改了Name属性)
CDemo(id=0719_1, name=set方法上添加@Autowired时修改了Name属性)

从这段代码中

可以看到@Autowired注解修饰的方法名称其实无所谓,重要的是将对象注入,这里获取到了BDemo和CDemo的bean对象,并将其赋值给BeanDemo.

从测试打印出来的结果可以看出,spring的Bean是单例,每次获取的值都是同一个.

在Beans里有提到,CDemo对象的值其实是从BDemo中获取过来的,而当bDemo的值在setBDemo方法中被修改之后,CDemo去获取的值也被修改.

补充一点

    @Bean
    public CDemo cDemoTest(BDemo bDemo){
        CDemo cDemo=new CDemo();
        cDemo.setId(bDemo.getId());
        cDemo.setName(bDemo.getName());
        return cDemo;
    }

 

这段代码等同于以下代码,所以拿到的bDemo对象实际上是从ioc容器中获取的

 @Bean
    public CDemo cDemoTest(@Autowired BDemo bDemo){
        CDemo cDemo=new CDemo();
        cDemo.setId(bDemo.getId());
        cDemo.setName(bDemo.getName());
        return cDemo;
    }

稍加修改,以下代码中bDemo对象则是直接调用bDemoTest方法获得,但是这里就会出现问题,这个bDemo对象是重新new出来的,并非ioc容器中的对象,所以bDemo不是单例.

    @Bean
    public CDemo cDemoTest(){
        CDemo cDemo=new CDemo();
        BDemo bDemo=bDemoTest();
        cDemo.setId(bDemo.getId());
        cDemo.setName(bDemo.getName());
        return cDemo;
    }

那么该如何解决这个问题呢?

答案很简单

使用@Configuration注解替换掉@Component

不配置@Configuration: 当内部方法 bean发⽣彼此依赖的时候会导致多例

配置之后:

                 1,会将配置的类(Beans)由普通类型转变为cglib代理类型

                 2,将将配置的类(Beans)的beanDefinitioin配置类属性赋值为full类型的(不配置的是lite)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值