zoukankan      html  css  js  c++  java
  • @Configuration 注解的用途

    why

    Spring实战中说:

    默认情况下,Spring中的bean都是单例的,我们并没有必要创建第二个完全相同(甚至可能不同,由@Bean注解的方法提供)的Bean实例。


    ......

    借助JavaConfig实现注入

    看起来,CompactDisc是通过调用sgtPeppers()得到的,但情况并非完全如此。
    因为sgtPeppers()方法上添加了@Bean注解,Spring将会拦截所有对它的调用,并确保直接返回该方法所创建的bean,而不是每次都对其进行实际的调用。

    @Configuration

    现在我们知道为什么有以下几个规则的原因了:

    1. @Configuration注解的类都必须是open类(类可以隐式地子类化,并且不能是最终的);
    2. @Configuration中的@Bean方法必须可重写;
    3. 为什么有@Configuration注解,明明@Component一样可以配置Bean;

    因为@Bean方法会被代理拦截!

    @Configuration
    open class A : InitializingBean, ApplicationContextAware {
        @Bean open fun getStr(): String { // 该方法实际只会被调用一次
            println("@Bean方法被调用")
            return "Hello"
        }
    
        var ctx: ApplicationContext? = null
        override fun afterPropertiesSet() {
            var value = ctx!!.getBean(String::class.java)
            println("bean = $value")
            value = getStr() // getStr被代理!
            println("bean = $value")
            value = getStr()
            println("bean = $value")
        }
    
        override fun setApplicationContext(applicationContext: ApplicationContext) {
            this.ctx = applicationContext
        }
    }
    

    输出是:

    @Bean方法被调用
    bean = Hello
    bean = Hello
    bean = Hello
    

    @Bean方法确实只被调用了一次,实在是匪夷所思。

    测试

    package test
    
    import org.junit.Assert
    import org.junit.Test
    import org.junit.runner.RunWith
    import org.springframework.beans.factory.annotation.Autowired
    import org.springframework.context.ApplicationContext
    import org.springframework.context.annotation.Bean
    import org.springframework.context.annotation.ComponentScan
    import org.springframework.context.annotation.Configuration
    import org.springframework.test.context.ContextConfiguration
    import org.springframework.test.context.junit4.SpringJUnit4ClassRunner
    import java.util.*
    
    @RunWith(SpringJUnit4ClassRunner::class)
    @ContextConfiguration(classes = [TestConfigBean::class])
    @ComponentScan
    class TestConfigBean {
        @Autowired lateinit var ctx: ApplicationContext
    
        @Test fun `时间戳正确性`() {
            val ta = currentTimeStamp()
            val tb = currentTimeStamp()
            println(ta)
            println(tb)
            Assert.assertNotEquals(ta, tb)
        }
    
        @Test fun `@Bean会被代理`() {
            val beanA = ctx.getBean(BeanA::class.java)
            println(beanA.productBeanA())
            println(beanA.productBeanA())
            Assert.assertEquals(beanA.productBeanA(), beanA.productBeanA())
        }
    }
    
    @Configuration    // <------- 此处如果换成@Component或者@Service,测试都会失败!说明只有使用@Configuration注解的类才会被代理
    open class BeanA {
        @Bean
        open fun productBeanA(): TimeStamp {
            println("only once!")
            return currentTimeStamp()
        }
    }
    
    data class TimeStamp(val value: Long)
    fun currentTimeStamp(): TimeStamp {
        Thread.sleep(1)
        return TimeStamp(Date().time)
    }
    
  • 相关阅读:
    数据库被注入daxia123原因及解决办法
    Alipay数字证书管理员权限问题
    关闭数据库的xp_cmdshell命令以防止黑客攻击
    如何使用JavaScript来写ASP程序
    VBscript操作DOM
    如何做好性能压测丨压测环境设计和搭建
    10倍性能提升!DLA SQL推出基于Alluxio的数据湖分析加速功能
    高德地图驾车导航内存优化原理与实战
    「直播实录」中英数据库专家谈:数据库的过去、未来和现在
    Flink 助力美团数仓增量生产
  • 原文地址:https://www.cnblogs.com/develon/p/14506494.html
Copyright © 2011-2022 走看看