自学了好一阵子,发现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; } }
package com.example.demo.pojo; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; @Data @AllArgsConstructor @NoArgsConstructor public class Pet { private String name; }
再创建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; }
方法2、在配置类添加注解 @EnableConfigurationProperties、在pojo类添加@ConfigurationProperties,适用于第三方的类注册进来
//@Component @ConfigurationProperties(prefix = "mycar") @Data public class Car { private String name; private Integer price; }
@Configuration(proxyBeanMethods = false) //告诉spring boot这是一个配置类==配置文件 @EnableConfigurationProperties(Car.class) public class Myconfig {