Java注解
-
@Deprecated
:标记方法或类过时 -
@SuppressWarning
: 在确定结果的前提下忽略警告
第三方注解
@Autoware
按运行机制分
- 源码注解(SOURCE):只在源码中存在
- 编译时注解(CLASS):源码和.class文件时都存在。
@Override
- 运行时注解(RUNTIME): 源码和.class文件存在、程序运行时也存在。
@Autoware
按来源分
- JDK
- 第三方
- 自定义
元注解 :给注解用的注解
自定义注解
- 语法:
- 使用
@interface
关键字 - 成员变量要生命成无参函数形式,并且无异常,只能是基本数据类型和String,使用
default
关键字赋默认值 - 只有一个成员变量时,必须命名为
value()
@Target({ElementType.METHOD,ElementType.TYPE})
@Rentention(RententionPolicy.RUNTIME)
@Inherited
@Document
public @interface Discription{
String desc();
String author();
int age() default 18;
}
- 元注解
-
@Target
:注解适用范围,可以设置多个。
取值:
ElementType.CONSTRUCTOR
ElementType.FIELD
ElementType.LOCAL_VARIABLE //局部变量
ElementType.METHOD
ElementType.PACKAGE
ElementType.PARAMETER
ElementType.TYPE //类,接口
-
@Rentention
:注解生命周期
取值:
RententionPolicy.SOURCE // 源码
RententionPolicy.CLASS // 编译
RententionPolicy.RUNTIME //运行
-
@Inherited
:允许注解继承 -
@Document
:生成doc时生成注解信息
- 使用注解
@Discription(desc="我是一段描述",author="yujian",age=18)
public String getMyName(){
return "yujian";
}
- 解析注解
通过反射获取类运行时注解信息,从而动态控制类的运行逻辑。
实战
自定义table和column注解映射字段和表,查询数据,打印书SQL
table和column注解:
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface Table {
String value();
}
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Column {
String value();
}
User类使用table和column注解
@Table("user")
public class User {
@Column("id")
private String id;
@Column("name")
private String name;
@Column("email")
private String email;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}
根据注解获取标名和字段名,根据反射获取字段值:
//获取class
Class c = user.getClass();
//获取table名称
if (!c.isAnnotationPresent(Table.class)){
return null;
}
Table table = (Table) c.getAnnotation(Table.class);
System.out.println(table.value());
//获取field名称
Field[] fields = c.getDeclaredFields();
for (Field field : fields){
if (field.isAnnotationPresent(Column.class)){
Column column = field.getAnnotation(Column.class);
System.out.print(column.value() + ":");
//通过反射获取对象值
String fieldName = field.getName();
String methodName = "get"
+ fieldName.substring(0,1).toUpperCase()
+ fieldName.substring(1);
try {
Method method = c.getMethod(methodName);
System.out.println(method.invoke(user));
} catch (Exception e) {
e.printStackTrace();
}
}
常见概念
-
为什么需要把
@Autowired
写在构造器上:注入注解要等类构造完成才会注入外部依赖,但变量是按顺序加载的,容易出现空指针异常,使用构造器注入在调用时去初始化,能保证已经注入了外部依赖。 -
@Autowired
只按照byType
注入;
@Resource
默认按byName
自动注入,也提供按照byType
注入; -
@Configuration
:配置文件,与@Bean
连用可配置单个Bean
,eg.@Bean(name="user")
-
@EnableAutoConfiguration
:配合spring.factories
文件将配置文件装配到spring中,参考。 -
@ComponentScan
:叠加在配置文件类上,可以定策略扫描Bean
,默认扫描配置文件同包的类,注意类上需要配置
//@Component注解。basePackages定义扫描的包
@ComponentScan(basePackages = { ” com.springboot . chapter3 . pojo” })
//basePackageClasses 定义扫描的类
@ComponentScan(basePackageClasses = {User. class} )
//还有 includeFilters 和 excludeFilters
@ComponentScan(basePackages = "com.springboot.chapter3 . * ”, excludeFilters = {@Filter(classes = {Service . class})}) 。
网友评论