@configuration注解_Spring注解@Configuration

前言

@Configuation是spring最常见的注解之一,很多人都很熟悉。说起这个注解的作用,大家一定会说,当类上有@Configuration的时候,可以在这个类中使用@Bean注解向spring容器中注册bean;如果没有@Configuration的时候,就无法注册Bean。事实真的是这样吗?

不使用@Configurtion

我们先看看传统注册bean的方式

<?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.xsd">    <bean id="qiaoyingzi" class="beans.vo.Student">        <property name="id" value="10086">property>        <property name="age" value="18">property>        <property name="name" value="乔英子">property>        <property name="city" ref="beijing">property>    bean>    <bean id="fangyifan" class="beans.vo.Student">        <property name="id" value="10087">property>        <property name="age" value="18">property>        <property name="name" value="方一凡">property>        <property name="city" ref="beijing">property>    bean>    <bean id="beijing" class="beans.vo.City">        <property name="id" value="110000">property>        <property name="name" value="北京">property>    bean>beans>
public class ConfigurationTest {    public static void main(String[] args) {        ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");        Student qiaoyingzi = (Student) ac.getBean("qiaoyingzi");        Student fangyifan = (Student) ac.getBean("fangyifan");        System.out.println(qiaoyingzi);        System.out.println(fangyifan);    }}

输出结果

Connected to the target VM, address: '127.0.0.1:59054', transport: 'socket'beans.vo.Student@367ffa75beans.vo.Student@49438269Disconnected from the target VM, address: '127.0.0.1:59054', transport: 'socket'Process finished with exit code 0

我们用xml向bean容器注册了三个Bean,一个是学生类的对象"乔英子",一个是学生类的对象"方一凡",一个是城市类的对象"北京",乔英子和方一凡都有个依赖对象"北京"。

使用@Bean,不用@Configuration

public class StudentConfig {    @Bean    public City beijing(){        System.out.println("城市类对象被创建");        return  new City(110000,"beijing");    }    @Bean    public Student qiaoyingzi(){        return new Student("10086","乔英子",18,beijing());    }    @Bean    public Student fangyifan(){        return new Student("10087","方一凡",18,beijing());    }}
public class ConfigurationTest {    public static void main(String[] args) {        AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();        ctx.register(StudentConfig.class);        ctx.refresh();        StudentConfig stuConfig=(StudentConfig) ctx.getBean("studentConfig");        Student qiaoyingzi= (Student)ctx.getBean("qiaoyingzi");        Student fangyifan= (Student)ctx.getBean("fangyifan");        System.out.println(stuConfig);        System.out.println(qiaoyingzi);        System.out.println(fangyifan);    }}

输出结果

Connected to the target VM, address: '127.0.0.1:58487', transport: 'socket'城市类对象被创建城市类对象被创建城市类对象被创建beans.annotation.configuration.StudentConfig@4135c3bbeans.vo.Student@6302bbb1beans.vo.Student@31304f14Disconnected from the target VM, address: '127.0.0.1:58487', transport: 'socket'

我们没有加@Configuration同样向spring容器注册了Bean,配置类对象,学生类对象和城市类对象都被注入,其中城市类的对象被创建了三次

加上@Configuration和@Bean 

我们只在StudentConfig上加上 @Configuration注解,再看输出结果

Connected to the target VM, address: '127.0.0.1:58499', transport: 'socket'城市类对象被创建beans.annotation.configuration.StudentConfig$$EnhancerBySpringCGLIB$$4fa8418e@740cae06beans.vo.Student@26d9b808beans.vo.Student@f78a47eDisconnected from the target VM, address: '127.0.0.1:58499', transport: 'socket'

乍一看没啥区别,其实我们可以发现,虽然两个学生类对象都有依赖对象"北京",但是城市对象只创建了一次,并且我们的配置类Bean StudentConfig打印信息多了"$EnhancerBySpringCGLIB$"这么一串东西。说明spring容器会用cglib为@Configuration修饰的类创建代理对象,被@Bean修饰的方法会全部被拦截,并且只执行一次。

总结:

  1. 不管@Bean所在的类是否有@Configuration注解,都可以将@Bean修饰的方法注册到spring容器

  2. @Configuration注解修饰的类,spring会通过cglib产生一个代理对象,并且拦截@Bean修饰的方法,可以确保一些bean是单例(总结参考路人甲java)

本文链接:https://my.lmcjl.com/post/4517.html

展开阅读全文

4 评论

留下您的评论.