java注解工作流程_Java注解解析

概念

注解是Java提供的一种 源程序中的元素关联任何信息和任何元数据的途径和方法。

Java常见注解

JDK自带注解

1. @Override 覆盖父类的方法

2. @Deprecated 让方法过时

3. @Suppvisewarnings 忽略警告

常见第三方注解(Spring为例)

1. @Autowired 可以对成员变量、方法和构造函数进行标注,来完成自动装配的工作。通过 @Autowired的使用来消除set ,get方法。

2. @Service 用于标注业务层组件。定义某个类为一个bean,则在这个类的类名前一行使用@Service("XXX"),就相当于讲这个类定义为一个bean,bean名称为XXX。而无需去xml文件内去配置。

3. @Repository 用于标注数据访问组件,即DAO组件。

注解分类

按运行机制分

1. 源码注解:注解只在源码中存在,编译成.class文件就不存在了

2. 编译时注解:注解在源码和.class文件中都存在(如:JDK内置系统注解)

3. 运行时注解:在运行阶段还起作用,甚至会影响运行逻辑的注解(如:Spring中@Autowried)

按照来源分

1. JDK内置注解

2. 自定义注解

3. 第三方注解

元注解——注解的注解

自定义注解

自定义注解的语法要求

1. 使用@interface关键字定义注解

2. 成员以无参无异常方式声明

3. 可以用default为成员指定一个默认值

390d7a526d53

image.png

4. 如果注解只有一个成员,则成员名必须取名value(),在使用时可以忽略成员名和赋值

号(=);

5. 成员类型是受限的,合法的类型包括原始数据类型和String,Class,Annotation,Enumeration

6. 注解类可以没有成员,没有成员的注解称为标识注解

390d7a526d53

image.png

元注解(注解里的注解)

1. @Target({ElementType.FIELD,ElementType.METHOD}):定义注解的作用域

CONSTRUCTOR 构造方法声明

FIELD 字段声明

LOCAL_VARIABLE 局部变量声明

METHOD 方法声明

PACKAGE 包声明

PARAMETER 参数声明

TYPE 类接口

2. @Retention(RetentionPolicy.RUNTIME):定义生命周期

SOURCE 只在源码显示,编译时会丢弃

CLASS 编译时会记录到class中,运行时忽略

RUNTIME 运行时存在,可以通过反射读取

3. @Inherited:允许子类继承父类上的注解。只能用在类上,如果用在接口上将不会起作用。也只能继承类上的注解,方法上的不能被继承。

4. @Documented:生成javadoc的时候包含注解

使用自定义注解

/* 自定义的注解类 */

import java.lang.annotation.Documented;

import java.lang.annotation.ElementType;

import java.lang.annotation.Inherited;

import java.lang.annotation.Retention;

import java.lang.annotation.RetentionPolicy;

import java.lang.annotation.Target;

@Target({ElementType.METHOD, ElementType.FIELD, ElementType.CONSTRUCTOR})

@Retention(RetentionPolicy.RUNTIME)

@Inherited

@Documented

public @interface Description{

int age() default 10;

String author();

String desc();

}

--------------------------------------------------------------------------------

/*

使用注解的语法:

@(=,=,...)

*/

@Description(desc="I am eyeColor",author="Mooc boy",age=18)

public String eyeColor(){

return "red";

}

解析注解

概念:通过反射获取类、函数或成员的运行时注解信息,从而实现动态控制程序运行的逻辑。

步骤:

使用类加载器加载类

找到类上边的注解

拿到注解实例

遍历方法上的注解

示例:

//自定义注解 Description.java

import java.lang.annotation.Documented;

import java.lang.annotation.ElementType;

import java.lang.annotation.Inherited;

import java.lang.annotation.Retention;

import java.lang.annotation.RetentionPolicy;

import java.lang.annotation.Target;

@Target({ElementType.METHOD, ElementType.FIELD, ElementType.TYPE})

@Retention(RetentionPolicy.RUNTIME)

@Inherited

@Documented

public @interface Description{

int age() default 10;

String author();

String desc();

}

// Person.class 用自定义注解修饰

@Description(desc="human class", author="wgp", age=20)

public class Person {

@Description(desc="walk method", author="gp", age=21)

public void walk(){

System.out.println("human can walk!");

}

}

// 注解解析类 Test.class

import java.lang.annotation.Annotation;

import java.lang.reflect.Method;

public class Test {

public static void main(String[] args) {

try {

//1\. 使用类加载器加载类

Class c = Class.forName("Person");

//2\. 找到类上面的注解

boolean isExist=c.isAnnotationPresent(Description.class);//isAnnotationParse()判断类上是否存在Description这样的注解

if(isExist){

//3.获得注解实例

Description d = (Description)c.getAnnotation(Description.class);

System.out.println(d.desc());

}

//4.找到方法上的注解

Method[] mts = c.getMethods();

for (Method mt : mts) {

if(mt.isAnnotationPresent(Description.class)){

Description d2 = (Description)mt.getAnnotation(Description.class);

System.out.println(d2.author());

}

}

//另外一种获取类上的注解的途径

Annotation[] annos = c.getAnnotations();

for (Annotation anno : annos) {

if(anno instanceof Description){

System.out.println(((Description) anno).author());

}

}

//另一种获取方法上的注解的途径

for (Method mt : mts){

Annotation[] annos2 = mt.getAnnotations();

for (Annotation anno : annos2) {

if(anno instanceof Description){

System.out.println(((Description) anno).desc());

}

}

}

} catch (Exception e) {

//TODO: handle exception

}

}

}

项目案例

说明:

代替Hibernate的解决方案,用在项目的持久层,核心代码就是用自定义注解实现的。

需求:

1. 有一张用户表,字段包含id,用户名,密码,地址,手机号;

2. 方便的对每个字段或者每个字段的组合进行检索,并打印出SQL。

分析:

1. 首先肯定有一个关于用户的JavaBean,包含所有用户信息;

2. 有了JavaBean需要将属性与字段匹配,也就是ORM;

3. 匹配完相当于拼接SQL语句时,知道表名和字段名称了,还缺少where中的字段值是多少;

4. 通过用户类的getter方法来获取字段值为多少,拼接完整SQL语句。

代码实现:

1. 用户类,我们希望用@Table和@Cloumn来绑定;

/**

* User:用户JavaBean

*/

@Table("user")

public class User {

@Column("id")

public Integer id;

@Column("user_name")

public String userName;

@Column("password")

public String passWord;

@Column("address")

public String address;

@Column("phone_num")

public String phoneNum;

public void setId(Integer id) {

this.id = id;

}

public void setUserName(String userName) {

this.userName = userName;

}

public void setPassWord(String passWord) {

this.passWord = passWord;

}

public void setAddress(String address) {

this.address = address;

}

public void setPhoneNum(String phoneNum) {

this.phoneNum = phoneNum;

}

public Integer getId() {

return id;

}

public String getUserName() {

return userName;

}

public String getPassWord() {

return passWord;

}

public String getAddress() {

return address;

}

public String getPhoneNum() {

return phoneNum;

}

}

2. 自定义@Table注解和@Column注解;

import java.lang.annotation.ElementType;

import java.lang.annotation.Retention;

import java.lang.annotation.RetentionPolicy;

import java.lang.annotation.Target;

@Target(ElementType.TYPE)

@Retention(RetentionPolicy.RUNTIME)

public @interface Table{

String value();

}

--------------------------------------------------------------------------

import java.lang.annotation.ElementType;

import java.lang.annotation.Retention;

import java.lang.annotation.RetentionPolicy;

import java.lang.annotation.Target;

@Target(ElementType.FIELD)

@Retention(RetentionPolicy.RUNTIME)

public @interface Column{

String value();

}

3. 根据反射来拼接出全部的SQL语句。

import java.lang.reflect.Field;

import java.lang.reflect.Method;

public class UserDao {

public static void main(String[] args) {

User user1 = new User();

user1.setId(0);

User user2 = new User();

user2.setUserName("ping");

User user3 = new User();

user3.setAddress("beijing");

user3.setPhoneNum("10101010101");

String sql1 = query(user1); //查询id为0用户

String sql2 = query(user2); //查询用户名含有ping的用户

String sql3 = query(user3); //查询满足多个条件的用户

System.out.println(sql1);

System.out.println(sql2);

System.out.println(sql3);

}

public static String query(User user) {

StringBuilder sBuilder = new StringBuilder();

Class clazz = user.getClass();

// 获取表名

if(!clazz.isAnnotationPresent(Table.class)){

return null;

}

Table table = (Table) clazz.getAnnotation(Table.class);

String tableName = table.value();

sBuilder.append("select * from ").append(tableName).append(" where 1 = 1");

// 获取所有字段名+值

Field[] fields = clazz.getDeclaredFields();

for (Field field : fields) {

if(!field.isAnnotationPresent(Column.class)){

continue;

}

Column column = field.getAnnotation(Column.class);

String columnName = column.value(); //字段名

String fieldName = field.getName(); //属性名

String getMethodName = "get"+fieldName.substring(0, 1).toUpperCase()+fieldName.substring(1); //get方法名

Object fieldValue = null; //属性值(先提升为Object类型)

try {

Method getMethod = clazz.getMethod(getMethodName);

fieldValue = getMethod.invoke(user); //执行get方法获取值

} catch (Exception e) {

e.printStackTrace();

}

//继续拼接SQL

if(fieldValue == null){

continue;

}

sBuilder.append(" and ").append(columnName);

if(fieldValue instanceof String){

sBuilder.append("='").append(fieldValue).append("'");

} else if(fieldValue instanceof Integer){

sBuilder.append("=").append(fieldValue);

}

}

return sBuilder.toString();

}

}

参考资料

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值