zoukankan      html  css  js  c++  java
  • java注解、spring bean

    自学了好一阵子,发现java注解这块实在是太重要了,故拿出来作为一篇笔记。

    一、定义

    1、注解与类、接口、枚举是在同一个层次,可以成为java 的一个类型。
    2、注解是一种元数据,它是一种描述数据的数据,其作用在于提供程序本身以外的一些数据信息,
    也就是说他不会属于程序代码本身,不参与逻辑运算,故而不会对原程序代码的操作产生直接的影响。

    @Override
    public String toString() {
        return"This is String Representation of current object.";
    }

    注解有什么好处?
    1、@Override告诉编译器这是一个重写方法(描述方法的元数据),
    2、父类中不存在该方法,编译器便会报错。
    3、如果拼写错误,例如将toString()写成了toStrring(),也不用@Override注解,程序依然能编译运行,但这不是我的期望结果。

    参考来源:https://blog.csdn.net/fei20121106/article/details/73733207

    大致分为三类:自定义注解、JDK内置注解、还有第三方框架提供的注解。

    1、自定义注解

    public class test {
    //    自定义注解:
    //    返回值类型只能是(基本类型、Class、String、enum)
    //    如果只有1个参数且名为value,使用时可以不用name=value的格式
    //    有设置默认值可以不写,比如Annotation2的age
        @Annotation1("")
        @Annotation2(value = "",employees = {"张三"})
        @Annotation3()
        public void testAnnotation(){};
    }
    
    // 四个元注解:
    // 元注解是注解的注解
    // Target表示注解使用范围,Retention表示在什么地方还有效
    // Documented表示生成javadoc文档,Inherited表示子类可以继承父类的注解
    @Target({ElementType.TYPE,ElementType.METHOD})
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Inherited
    @interface Annotation1{
        String value();
    }
    
    @Target(ElementType.METHOD)
    @interface Annotation2{
        String value();
        String[] employees();
        int age() default 12;
    }
    
    @interface Annotation3{
    }

    2、 内置注解
      @Overide 重写
      @Deprecated 不推荐使用,但是可以使用
      @SuppressWarnings 抑制编译时的警告信息
        抑制单类型的警告   @SuppressWarnings("unchecked")
        抑制多类型的警告   @SuppressWarnings(value={"unchecked", "rawtypes"})
        抑制所有类型的警告  @SuppressWarnings("all")

    3、第三方注解

      比如 lombok、spring框架的注解

    二、 spring bean

    这里涉及到ioc概念,之前的文章有写:https://www.cnblogs.com/yinwenbin/p/15170294.html

    Bean是Spring框架中最核心的两个概念之一,另一个是面向切面编程AOP;
    在 Spring 中,构成应用程序主干并由Spring IoC容器管理的对象称为bean
    类的实例化、依赖的实例化、依赖的传入  都交由 Spring  IoC容器控制, 而不是用new方式实例化对象、通过非构造函数方法传入依赖等常规方式。

    bean规范如下:
    1、所有属性为private
    2、提供默认构造方法
    3、提供getter和setter
    4、实现serializable接口

    注册和使用,参考来源:https://zhuanlan.zhihu.com/p/99870991
    使用Bean:即是把已经在xml文件中配置好的Bean拿来用,完成属性、方法的组装;比如@Autowired , @Resource(@Autowired注解由Spring提供,只按照byType注 入;@resource注解由J2EE提供,默认按照byName自动注入
    注册Bean:这些注解都是把你要实例化的对象转化成一个Bean,放在Spring IoC容器中
      @Component , 组件
      @Repository ,数据库层组件
      @Controller , 控制器组件
      @Service ,业务逻辑组件
      @Configuration , 配置组件
      @Bean
        1、用于显式声明单个bean,而不是让Spring像上面那样自动执行它。它将bean的声明与类定义分离,并允许您精确地创建和配置bean。
        2、如果想将第三方的类变成组件,你又没有没有源代码,也就没办法使用@Component进行自动配置,这种时候使用@Bean就比较合适了。
        3、@Bean则常和@Configuration注解搭配使用。

    有些项目不想一个一个从xml迁移,只需要随便在某一个配置类上添加注解@ImportResource,示例:@ImportResource("classpath:beans.xml")

    下面示例是在springboot运行的,先创建2个pojo类

    package com.example.demo.pojo;
    import lombok.AllArgsConstructor;
    import lombok.Data;
    import lombok.NoArgsConstructor;
    
    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    public class User {
        private String name;
        private Integer age;
    
        private Pet pet;
    
        public User(String name, Integer age) {
            this.name = name;
            this.age = age;
        }
    }
    View Code
    package com.example.demo.pojo;
    
    import lombok.AllArgsConstructor;
    import lombok.Data;
    import lombok.NoArgsConstructor;
    
    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    public class Pet {
        private String name;
    }
    View Code

    再创建config类

    package com.example.demo.config;
    
    import ch.qos.logback.core.db.DBHelper;
    import com.example.demo.pojo.Pet;
    import com.example.demo.pojo.User;
    import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.context.annotation.Import;
    
    /*
    1、配置类里面用 @Bean 标注在方法上给容器注册组件,默认也是单实例
    2、配置类本身也是组件
    3、proxyBeanMethods :代理bean的方法,默认为true
     */
    @Import({User.class, DBHelper.class}) //给容器中自动创建出这2个组件
    @Configuration(proxyBeanMethods = false) //告诉spring boot这是一个配置类==配置文件
    public class Myconfig {
    
        /*
        proxyBeanMethods
        如果为True, 获取到的类组件就是代理对象。代理对象多次调用组件方法,每次都会检查容器是否有实例对象,
        保持组件单实例。配置类组件间有依赖时使用
        如果为false,获取到的类组件就是普通对象。普通对象多次调用组件方法,不会检查容器是否有实例对象(导致springboot启动会比较快),
        会产生多个实例。配置类组件间无依赖时使用
         */
        @ConditionalOnBean(name = "ziDingYi") //如果容器中有该组件才注册bean,放在类上则下面的函数都会生效。加载顺序问题,用@ConditionalOnClass靠谱一点
        @Bean //给容器中添加组件,以方法名作为组件的id,第一个字母小写。返回类型就是组件类型。方法返回的值就是组件在容器中的实例
        public User user02(){
            User zhangsan=new User("张三",18);
            // User 组件依赖了 Pet组件。如果proxyBeanMethods为false,那么下一行的tomcatPet()会创建新的实例
            zhangsan.setPet(tomcatPet());
            return zhangsan;
        }
    
    
        @Bean("ziDingYi") // 这里的 ziDingYi 是我们自定义的组件id
        public Pet tomcatPet(){
            return new Pet("tomcat");
        }
    }

    最后在主程序验证

    package com.example.demo;
    
    import com.example.demo.config.Myconfig;
    import com.example.demo.pojo.Pet;
    import com.example.demo.pojo.User;
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.context.ConfigurableApplicationContext;
    
    @SpringBootApplication
    public class DemoApplication {
    
        public static void main(String[] args) {
            ConfigurableApplicationContext run = SpringApplication.run(DemoApplication.class, args);
    
            //查看容器的组件
            String[] names=run.getBeanDefinitionNames();
            for (String name:names){
                System.out.println(name);
            }
    
            // 从容器中获取组件3种方法
            // 根据id、类型查找bean(getBean的返回类型是T,传入Pet.class则意味着返回Pet类型)
            Pet pet=run.getBean("ziDingYi", Pet.class);
            System.out.println("Pet实例:"+pet);
    
            // 按照id查找bean(返回的类型是object,所以要强转)
            User user =(User)run.getBean("user02");
            System.out.println("User实例:"+user);
    
            // 按照类型查找bean(要求该类型只有唯一的对象,否则不能找到)
            Myconfig bean = run.getBean(Myconfig.class);
            System.out.println("Myconfig 实例:"+bean);
    
            // 如果proxyBeanMethods为true,则打印结果为true,否则反之。
            System.out.println("测试proxyBeanMethods为true、false的情况:"+(user.getPet()==pet));
        }
    }

     从properties文件装配2种方法 

    mycar.name=BYD
    mycar.price=100000

    方法1、在pojo类上添加注解 @Component、@ConfigurationProperties

    @Component
    @ConfigurationProperties(prefix = "mycar")
    @Data
    public class Car {
        private String name;
        private Integer price;
    }
    View Code

    方法2、在配置类添加注解 @EnableConfigurationProperties、在pojo类添加@ConfigurationProperties,适用于第三方的类注册进来

    //@Component
    @ConfigurationProperties(prefix = "mycar")
    @Data
    public class Car {
        private String name;
        private Integer price;
    }
    View Code
    @Configuration(proxyBeanMethods = false) //告诉spring boot这是一个配置类==配置文件
    @EnableConfigurationProperties(Car.class)
    public class Myconfig {
    View Code
    一个只会点点点的测试,有疑问可以在测试群(群号:330405140)问我
  • 相关阅读:
    获取指定<文字行数>的<高度>是多少 TextKit
    JS 与 OC 交互
    PHP-note
    MySQL函数
    freeSWITCH之多平台测试通信
    freeSWITCH之安装
    PHP面向对象
    MySQL Optimization 优化原理
    理解常量指针与指针常量?
    InterView之PHP(2)
  • 原文地址:https://www.cnblogs.com/yinwenbin/p/15322009.html
Copyright © 2011-2022 走看看