温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

@Bean怎么使用

发布时间:2022-08-23 14:21:48 来源:亿速云 阅读:220 作者:iii 栏目:开发技术

今天小编给大家分享一下@Bean怎么使用的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。

    @Bean是一个方法级别上的注解,主要用在@Configuration注解的类里,也可以用在@Component注解的类里。

    目的是创建一个类。当spring需要创建指定的一个类时会调用这个注解(@Bean)的方法。

    一个对象

    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    public class Info {
        String name;
        int age;
    }

    就如同在在xml配置中添加一个类的配置。这样spring在自动创建这个类时会调用配置的方法。

    <bean id="info" class="zhong.test.springbootdemo.usultestdemo.demo.Info">
        <property name="name" value="sjl"/>
        <property name="age" value="18"/>
    </bean>

    SprignBoot中 @Bean 完美的替换了了上面的这种在xml中配置的方法。使用以下方法就能让spring在需要自动创建Info对象时,自动调用这个方法。

    @Configuration
    public class BeanInit {
        /**
         * 测试@Bean的作用
         */
        @Bean(name = "info")
        public Info getInfo(){
            return new Info("gfagduis", 2343);
        }
        @Bean(name = "info1")
        public Info getInfo1(){
            return new Info("gfagdufasfdfdais", 2343);
        }
    }

    获取这个类的方法

    1、AnnotationConfigApplicationContext 类获取

    @Component
    public class BeanTest implements CommandLineRunner {
        private void getBean(){
            ApplicationContext ctx = new AnnotationConfigApplicationContext(BeanInit.class);
            Info info1= ctx.getBean("info",Info.class);
            System.out.println(info1);
        }
        @Override
        public void run(String... args) throws Exception {
            System.out.println(">>>>>>>>>>>>>>>服务启动执行,执行加载数据等操作<<<<<<<<<<<<<");
            getBean();
        }
    }

    2、在spring自动创建的类中

    在构造方法中设置这个值,这样spring就会调用该类的创建方法来获取这个初始化的类。

    @Component
    public class BeanTest implements CommandLineRunner {
        private Info info;
        /**
         *spring创建BeanTest对象时会调用这个构造函数。参数是info1,所以会调用 @Bean(name = "info1") 注释的方法
         *
         */
        public BeanTest (Info info1){
            this.info = info1;
        }
        
       private void getBean2(){
            System.out.println(info);
        }
        @Override
        public void run(String... args) throws Exception {
            System.out.println(">>>>>>>>>>>>>>>服务启动执行,执行加载数据等操作<<<<<<<<<<<<<");
            getBean2();
        }
    }

    在构造函数中 BeanTest (Info info1) 参数的名称是info1.所以就调用 @Bean(name = “info1”) 的方法来获取初始化对象。

    结果如下:

                              >>>>>>>>>>>>>>>服务启动执行,执行加载数据等操作<<<<<<<<<<<<<
                             Info(name=gfagdufasfdfdais, age=2343)

    同时也是支持多别名配置的 例如:

        @Bean(name = { "info12", "info3", "info3" })
        public Info getInfo2(){
            return new Info("gfa4361783ais", 2343);
        }

    测试一下

    @Component
    public class BeanTest implements CommandLineRunner {
        private Info info;
        private Info info1;
        private Info info2;
        /**
         *spring创建BeanTest对象时会调用这个构造函数。参数是info1,所以会调用 @Bean(name = "info1") 注释的方法
         *
         */
        public BeanTest (Info info1, Info info2, Info info3){
            this.info = info1;
            this.info1 = info2;
            this.info2 = info3;
        }
        
       private void getBean2(){
            System.out.println(info);
            System.out.println(info1);
            System.out.println(info2);
        }
        @Override
        public void run(String... args) throws Exception {
            System.out.println(">>>>>>>>>>>>>>>服务启动执行,执行加载数据等操作<<<<<<<<<<<<<");
            getBean2();
        }
    }

    结果如下

    >>>>>>>>>>>>>>>服务启动执行,执行加载数据等操作<<<<<<<<<<<<<
    Info(name=gfagdufasfdfdais, age=2343)
    Info(name=gfa4361783ais, age=2343)
    Info(name=gfa4361783ais, age=2343)

    当然也可以使用 Qualifier(“xxx”) 来指定 @Bean(name = “xxx”) 中的xxx就可以调用对应的方法。

    3、使用 @Autowired 注解获取变量

    如果有多个初始化方法,则会根据变量名称来获取。

    在初始化类中建立以下多个初始方法

     @Configuration
    public class BeanInit {
        /**
         * 测试@Bean的作用
         */
        @Bean/*(initMethod = "init")*/
        public Info getInfo(){
            System.out.println("进入方法");
            Info info = new Info("gfagduis", 2343);
            System.out.println("结束方法");
            return info;
        }
        @Bean(name = "info1")
        public Info getInfo1(){
            return new Info("gfagdufasfdfdais", 2343);
        }
        @Bean(name = { "info2", "info3", "info3" })
        public Info getInfo2(){
            return new Info("gfa4361783ais", 2343);
        }
        @Bean
        public Info info(){
            return new Info("gfsdfadsfad4361783ais", 23143);
        }

    然后在测试方法中分别用 @Autowired注释Info类来获取对应的对象

    @Component
    public class BeanTest implements CommandLineRunner {
        //private Info info;
        @Autowired
        private Info getInfo;
        @Autowired
        private Info info1;
        @Autowired
        private Info info3;
        @Autowired
        private Info info;
        /*public BeanTest (Info info){
            this.info = info;
        }*/
        private void getBean(){
            /*ApplicationContext ctx = new AnnotationConfigApplicationContext(BeanInit.class);
            Info person = ctx.getBean("info",Info.class);
            System.out.println(person);*/
            System.out.println(getInfo);
            System.out.println(info1);
            System.out.println(info3);
            System.out.println(info);
        }
        @Override
        public void run(String... args) throws Exception {
            System.out.println(">>>>>>>>>>>>>>>服务启动执行,执行加载数据等操作<<<<<<<<<<<<<");
            getBean();
        }
    }

    测试结果如下:

    >>>>>>>>>>>>>>>服务启动执行,执行加载数据等操作<<<<<<<<<<<<<
    Info(name=gfagduis, age=2343)
    Info(name=gfagdufasfdfdais, age=2343)
    Info(name=gfa4361783ais, age=2343)
    Info(name=gfsdfadsfad4361783ais, age=23143)

    在使用 @Autowired 注解时,也可以与 @Qualifier(“xxx”) 指定使用哪个方法来获取对象。

    @Bean 注解的属性解析

    value 和 name

    name 和 value 两个属性是相同的含义的, 在代码中定义了别名。 为 bean 起一个名字,如果默认没有写该属性,那么就使用方法的名称为该 bean 的名称

    autowire

    装配方式 有三个选项

    • Autowire.NO (默认设置)

    • Autowire.BY_NAME

    • Autowire.BY_TYPE

    指定 bean 的装配方式, 根据名称 和 根据类型 装配, 一般不设置,采用默认即可。

    initMethod

    bean 的初始化方法, 直接指定方法名称即可,不用带括号。初始方法要在对应的POHO中,也就是Info类中。

    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    public class Info {
        String name;
        int age;
        private void init(){
            System.out.println("进入方法2");
            name = "fhasjdf";
            age = 12;
        }
    }
    @Configuration
    public class BeanInit {
        /**
         * 测试@Bean的作用
         */
        @Bean(name = "info", initMethod = "init")
        public Info getInfo(){
            System.out.println("进入方法");
            Info info = new Info("gfagduis", 2343);
            System.out.println("结束方法");
            return info;
        }

    最终结果、:

    进入方法
    结束方法
    进入方法2
    2019-09-24 14:57:11.917  INFO 11656 --- [           main] o.s.s.concurrent.ThreadPoolTaskExecutor  : Initializing ExecutorService 'applicationTaskExecutor'
    2019-09-24 14:57:12.048  INFO 11656 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8080 (http) with context path ''
    2019-09-24 14:57:12.051  INFO 11656 --- [           main] z.t.s.u.start.UsulTestStartApplication   : Started UsulTestStartApplication in 1.74 seconds (JVM running for 2.246)
    >>>>>>>>>>>>>>>服务启动执行,执行加载数据等操作<<<<<<<<<<<<<
    Info(name=fhasjdf, age=12)

    所以最终调用的是init()方法来创建类。

    destroyMethod

    bean 的销毁方法, 在调用 IoC 容器的 close() 方法时,会执行到该属性指定的方法。不过,只是单实例的 bean 才会调用该方法,如果是多实例的情况下,不会调用该方法。

    注意:

    由于spring构造的对象都是单例的,所以只要是从spring ioc中获取的对象都是同一个,他们中的属性,即便是私有的非静态属性。都是公用的。

    public class MyDisposableBean implements DisposableBean {
        public Map<String, String> map = new HashMap<>();
        int i = 0;
        private void init(){
            System.out.println("MyDisposableBean自定义初始化方法");
        }
        private void destroyMethod(){
            System.out.println("自定义销毁方法,MyDisposableBean对象销毁");
        }
        public void pringt(){
            System.out.println("-------------------------------");
            System.out.println("i=" + i);
            System.out.println("map.size=" + map.size());
            map.entrySet().stream().forEach(item -> System.out.println("map ->   "+ item.getKey() + "---" + item.getValue()));
        }
    }
    @Configuration
    public class BeanConfigurer {
        @Bean(name = "MyDisposableBean", initMethod = "init", destroyMethod = "destroyMethod")
        public MyDisposableBean getMyDisposableBean(){
            System.out.println("MyDisposableBean构造方法");
            return new MyDisposableBean();
        }
    }
    @Component
    public class DisposableBeanTest implements CommandLineRunner {
        @Override
        public void run(String... args) throws Exception {
            MyDisposableBean myDisposableBean = new MyDisposableBean();
            MyDisposableBean myDisposableBean1 = new MyDisposableBean();
            MyDisposableBean myDisposableBean2 = SpringContextUtils.getBean(MyDisposableBean.class);
            myDisposableBean2.pringt();
            myDisposableBean2.map.put("1", "2");
            myDisposableBean2.i = 2;
            MyDisposableBean myDisposableBean3 = SpringContextUtils.getBean(MyDisposableBean.class);
            myDisposableBean3.pringt();
            myDisposableBean1.pringt();
        }
    }

    测试结果:

    MyDisposableBean构造方法
    MyDisposableBean自定义初始化方法
    -------------------------------
    i=0
    map.size=0
    -------------------------------
    i=0
    map.size=0
    -------------------------------
    i=2
    map.size=1
    map ->   1---2
    -------------------------------
    i=0
    map.size=0

    可以看出,如果是我们自己在程序中new的对象(myDisposableBean 和 myDisposableBean1),其私有属性map和i是不变的。不相互影响。

    另外两从spring ioc中获取的对象(myDisposableBean2 和 myDisposableBean3 )的map和i两个属性,是公用的。其中一个对象修改值,name另外一个对象的属性也相应的变化

    以上就是“@Bean怎么使用”这篇文章的所有内容,感谢各位的阅读!相信大家阅读完这篇文章都有很大的收获,小编每天都会为大家更新不同的知识,如果还想学习更多的知识,请关注亿速云行业资讯频道。

    向AI问一下细节

    免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

    AI