码迷,mamicode.com
首页 > 编程语言 > 详细

05-SpringBoot容器与底层注解-1

时间:2021-06-17 17:12:52      阅读:0      评论:0      收藏:0      [点我收藏+]

标签:修改   main   code   EAP   spring容器   一个   除了   功能   lan   

容器功能

在idea-springboot工程中新建一个springboot项目 b-springboot-annotation,新建一个bean包表示要让容器创建的类和一个config包表示存放配置类,具体使用如下

bean包中有两个类User和Pet

package com.studymyself.bean;

public class User {

    private String name;

    public User() {
    }

    public User(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "User{" +
                "name=‘" + name + ‘\‘‘ +
                ‘}‘;
    }
}

package com.studymyself.bean;

public class Pet {

    private String name;

    public Pet() {
    }

    public Pet(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "Pet{" +
                "name=‘" + name + ‘\‘‘ +
                ‘}‘;
    }
}

1、组件添加(容器创建javabean)

1.1 注解@Configuration

  • 在config包中创建一个MyConfig类,其中定义类的上面添加@Configuration注解,该注解的主要作用就是表示这个类是一个配置类,等同于spring中的配置文件。在这个类中新建一个方法,返回值是一个User,方法内容是new一个User实例,然后返回,在方法定义的上面添加@Bean,表示该方法返回的对象作为组件放进spring容器中了,具体内容如下:
/**
 * @Configuration:
 *  1、在类上面添加该注解,告诉spring boot这个类是一个配置类,等同于容器的配置文件
 *  2、当然,这个配置类的对象也是一个组件,被放到容器中。
 */
@Configuration
public class MyConfig {

    /**
     * @Bean:
     *  1、放在方法上面表示给容器添加组件,组件值是返回的实例,默认将该方法名作为组件(返回的实例)的id,
     *  2、通过测试,放进容器中的组件是单实例的
     	3、可以修改其默认的组件id名,注解中注解中 @Bean(name = "aa")这样修改
     */
    @Bean
    public User user01(){
        User user = new User("张三");
        return user;
    }

    @Bean
    public Pet tomcat(){
       Pet pet = new Pet("tomcat");
        return pet;
    }
}

  • 在main主程序类中进行验证,内容如下:
    @SpringBootApplication
    public class BSpringbootAnnotationApplication {
    
    	public static void main(String[] args) {
    		//获取容器对象
    		ConfigurableApplicationContext run = SpringApplication.run(BSpringbootAnnotationApplication.class, args);
    
    		//验证从容器中获取在配置类中添加的组件user01和tomcat
    		User user1 = run.getBean("user01",User.class);
    		Pet pet = run.getBean("tomcat",Pet.class);
    		System.out.println(user1+"\n"+pet);
    
    		//再获取一次user01,跟第一次获取的比较,验证是否是同一个
    		User user2 = run.getBean("user01",User.class);
    		System.out.println(user1==user2);
            
            //验证配置类也被创建对象作为组件放进容器中
    		MyConfig bean = run.getBean(MyConfig.class);
    		System.out.println(bean);
    		//com.studymyself.config.MyConfig$$EnhancerBySpringCGLIB$$767ae820@56febdc
    
    	}
    
    }
    结果:
    User{name=‘张三‘}
    Pet{name=‘tomcat‘}
    true
    
    可以看到,容器中已经放入了User类和Pet类的组件,而且仍然默认是单实例的例的。配置类也是一个组件,而且默认是使用CGLIB动态代理进行功能增强了的代理对象组件。
  • 验证当@Configuration注解中属性proxyBeanMethods=true时,调用配置类中的方法,到底是普通的调用方法还是到容器中获取,main方法中添加如下
    @SpringBootApplication
    public class BSpringbootAnnotationApplication {
    
    	public static void main(String[] args) {
    		//获取容器对象
    		ConfigurableApplicationContext run = SpringApplication.run(BSpringbootAnnotationApplication.class, args);
    
    		//验证从容器中获取在配置类中添加的组件user01和tomcat
    		User user1 = run.getBean("user01",User.class);
    		Pet pet = run.getBean("tomcat",Pet.class);
    		System.out.println(user1+"\n"+pet);// User{name=‘张三‘} Pet{name=‘tomcat‘}
    
    		//再获取一次user01,跟第一次获取的比较,验证是否是同一个
    		User user2 = run.getBean("user01",User.class);
    		System.out.println(user1==user2);//true
    
    		//验证配置类也被创建对象作为组件放进容器中
    		MyConfig myConfig = run.getBean(MyConfig.class);
    		System.out.println(myConfig);
    		//com.studymyself.config.MyConfig$$EnhancerBySpringCGLIB$$767ae820@56febdc
    
    		//验证@Configuration注解中属性proxyBeanMethods=true时,调用配置类中的方法
    		User user3 = myConfig.user01();
    		User user4 = myConfig.user01();
    		System.out.println(user3==user4);//true
    
    	}
    
    }
    结果:
    User{name=‘张三‘}
    Pet{name=‘tomcat‘}
    true
    com.studymyself.config.MyConfig$$EnhancerBySpringCGLIB$$767ae820@56febdc
    true
    
    
    可以看到,proxyBeanMethods=true时,调用该方法,业务是MyConfig类的代理对象调用方法,有功能增强,所以底层是先到容器中查看是否有User.class这个类的实例,如果没有,就执行new方法创建一个放到容器中,返回该实例,如果有直接从容器中获取返回。这样确保组件的单实例。
  • 验证当@Configuration注解中属性proxyBeanMethods=false时,调用配置类中的方法,到底是普通的调用方法还是到容器中获取,main方法中添加如下
    @SpringBootApplication
    public class BSpringbootAnnotationApplication {
    
    	public static void main(String[] args) {
    		//获取容器对象
    		ConfigurableApplicationContext run = SpringApplication.run(BSpringbootAnnotationApplication.class, args);
    
    		//验证从容器中获取在配置类中添加的组件user01和tomcat
    		User user1 = run.getBean("user01",User.class);
    		Pet pet = run.getBean("tomcat",Pet.class);
    		System.out.println(user1+"\n"+pet);// User{name=‘张三‘} Pet{name=‘tomcat‘}
    
    		//再获取一次user01,跟第一次获取的比较,验证是否是同一个
    		User user2 = run.getBean("user01",User.class);
    		System.out.println(user1==user2);//true
    
    		//验证配置类也被创建对象作为组件放进容器中
    		MyConfig myConfig = run.getBean(MyConfig.class);
    		System.out.println(myConfig);
    		//com.studymyself.config.MyConfig$$EnhancerBySpringCGLIB$$767ae820@56febdc
             //com.studymyself.config.MyConfig@4dd94a58
    
    //		//验证@Configuration注解中属性proxyBeanMethods=true时,调用配置类中的方法
    //		//这里就是代理对象调用方法
    //		User user3 = myConfig.user01();
    //		User user4 = myConfig.user01();
    //		System.out.println(user3==user4);//true
    
    		//验证@Configuration注解中属性proxyBeanMethods=false时,调用配置类中的方法
    		//这里就是MyConfig的普通对象调用方法
    		User user3 = myConfig.user01();
    		User user4 = myConfig.user01();
    		System.out.println(user3==user4);//false
    
    	}
    
    }
    
    结果:
    User{name=‘张三‘}
    Pet{name=‘tomcat‘}
    true
    com.studymyself.config.MyConfig@4dd94a58
    false
    
    
    可以看到,proxyBeanMethods=false时,调用该方法,业务是MyConfig类的普通对象调用方法,没有功能增强,所以直接调用运行其中的方法,创建了两个不同的对象。
  • 由以上可以知道,proxyBeanMethods的值对应两种模式:Full模式(也叫全模式proxyBeanMethods=true)和Lite模式(也叫轻量级模式proxyBeanMethods=false)
    	使用Full模式的前提是你项目中的组件有组件依赖,比如说User类中有一个Pet类型的属性,当User和Pet类下组件都被放到容器中后,User组件中的Pet属性希望使用的是容器中的Pet组件,就是依赖于这个容器中的Pet组件,需要使用Full模式。
    	当我们使用的这些组件都不依赖于容器中的组件,那么就使用Lite模式。
    	--结论:
    	配置类组件之间无依赖关系用Lite模式加速容器启动过程,减少判断
    	配置类组件之间有依赖关系,方法会被调用得到之前单实例组件,用Full模式
    
  • 除了@Bean注解是将扫描到的方法的返回值封装到容器中外,还有@Component、@Controller、@Service、@Respository这些之前用的注解写在被扫描的包的范围内的类上,被扫描到,创建修饰的类的对象,然后封装到容器。
  • 主程序类,一般也被称为主配置类,可以写配置。一般我们自己创建配置类来写配置

05-SpringBoot容器与底层注解-1

标签:修改   main   code   EAP   spring容器   一个   除了   功能   lan   

原文地址:https://www.cnblogs.com/rjzhong/p/14892960.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!