一、Java注解编程
在开发过程中我们会看到,继承接口会出现@Override注解,有时候还会提示写注解@SuppressWarnings
还有在使用Spring,Mybatis,Struts2等框架时,常常会使用注解,很多人都知道这些怎么使用,但是不知道他是怎么来的。其实,这是Java的特性
通过学习注解编程我们可以
1.能够读懂别人写的代码,特别是框架相关的代码
2.编程更加简洁,代码更加清晰
Java注解是一种代码级别的说明。它是JDK1.5及以后版本引入的一个特性,与类、接口、枚举是在同一个层次。它可以声明在包、类、字段、方法、局部变量、方法参数等的前面,用来对这些元素进行说明,注释。
二、注解的分类
这里引用网友的一张图:http://www.cnblogs.com/xing901022/p/3966799.html
上图分类可以分为三类:注解大体上分为三种:标记注解,一般注解,元注解,也可以按照如下机制分类
2.1按照运机制分为
源码注解编译时的注解
运行时的注解
源码注解:注解只在源码存在,编译成.class文件就不存在了
编译时注解:注解在源码和.class中都存在 (如@Override,@Deprecated,@Suppvisewarnings)
运行时注解:在运行阶段还会起作用,甚至会影响运行逻辑的注解(@Autowired)
2.2按照注解的来源
来自JDK的注解来自第三方的注解
自定义的注解
2.3元注解
给注解进行的注解三、常见的注解实例
@Deprecated //声明某个方法过时了
@Suppvisewarnings //忽略警告,抑制编译器发出特定的警告
@Suppvisewarnings 忽略警告,抑制编译器发出特定的警告
在我们调用过时的方法或其他情况下我们会看到编译器给我们发出告警
我们可以使用@Suppvisewarnings("抑制那种告警的注解名"),如下,告警消失了
还有一些常见的第三方框架的注解
Spring @Autowired @Service @Repository
Mybatis @InserProvider @UpdateProvier @Options
四、自定义注解
注解的注解(元注解)
使用自定义注解
解析注解
4.1自定义注解的语法要求
4.2注解的注解(元注解)
ElemenetType.CONSTRUCTOR 构造器声明
ElemenetType.FIELD 域声明(包括 enum 实例)
ElemenetType.LOCAL_VARIABLE 局部变量声明
ElemenetType.METHOD 方法声明
ElemenetType.PACKAGE 包声明
ElemenetType.PARAMETER 参数声明
ElemenetType.TYPE 类,接口(包括注解类型)或enum声明
@Retention : 表示在什么级别保存该注解信息。可选的参数值在枚举类型 RetentionPolicy 中,包括:
RetentionPolicy.SOURCE 注解将被编译器丢弃
RetentionPolicy.CLASS 注解在class文件中可用,但会被VM丢弃
RetentionPolicy.RUNTIME VM将在运行期也保留注释,因此可以通过反射机制读取注解的信息。
@Documented : 将此注解包含在 javadoc 中 ,它代表着此注解会被javadoc工具提取成文档。在doc文档中的内容会因为此注解的信息内容不同而不同。
@Inherited :注解类中使用该注解标识,如果类中使用了该注解,子类会继承类中(只有在继承的时候生效,而且只会继承类中的注解,方法或属性中的注解不会生效)的注解
五、注解的解析
自定义注解类:
-
@Target({ElementType.METHOD,ElementType.TYPE})
-
@Retention(RetentionPolicy.RUNTIME)
-
@Inherited
-
@Documented
-
public
@interface Description {
-
-
String value();
-
}
Person.java
-
package com.ann.test;
-
-
@Description("I am a class annotation")
-
public
class Person {
-
-
@Description("I am a method annotation")
-
public String name() {
-
return
null;
-
}
-
-
@Description("I am a method annotation")
-
public int age(){
-
return
0;
-
}
-
-
@Deprecated
//注解说明该方法过时了
-
public void sing(){
-
-
}
-
}
Child.java,继承Person,验证@Inherited
-
package com.ann.test;
-
-
public
class Child extends Person {
-
-
@Override
-
public String name() {
-
return
null;
-
}
-
-
@Override
-
public int age() {
-
return
0;
-
}
-
-
@Override
-
public void sing() {
-
-
}
-
-
}
-
package com.ann.test;
-
-
import java.lang.annotation.Annotation;
-
import java.lang.reflect.Method;
-
-
/*
-
* 通过反射解析注解
-
* */
-
public
class ParseAnn {
-
-
public static void main(String[] args) {
-
//1.使用类加载器加载类
-
try{
-
Class c = Class.forName(
"com.ann.test.Child");
-
//2.找到类上边的注解
-
boolean isExist = c.isAnnotationPresent(Description.class);
-
if(isExist){
-
//
3.拿到注解实例
-
Description description = (Description) c.getAnnotation(Description.class);
-
System.out.println(description.value()+"---
1
");
-
}
-
-
//4.找到方法上的注解
-
Method[] methods =c.getMethods();
-
for(Method method:methods){
-
boolean isMExist = method.isAnnotationPresent(Description.class);
-
if(isMExist){
-
//5.拿到方法上的注解实例
-
Description dmethod = method.getAnnotation(Description.class);
-
System.out.println(dmethod.value()+"---
2
");
-
}
-
}
-
-
//获取所有的方法上的注解
-
for(Method m:methods){
-
Annotation[] annotations = m.getAnnotations();
-
for(Annotation annotation:annotations){
-
if(annotation instanceof Description){
-
Description d = (Description)annotation;
-
System.out.println(d.value()+"---
3
");
-
}
-
}
-
}
-
}catch(ClassNotFoundException e){
-
e.printStackTrace();
-
}
-
}
-
-
}
-
结果:
I am a class annotation---1
从结果可以看出,只有类上的注解被继承类,通过反实现一个仿照Hibernate的解决方案,核心代码通过注解实现
六、仿照Hibernate自定义注解实现
2.为方便对每个字段的组合条件进行检索,并打印出SQL
3.使用方式足够简单射可以很方便的解析出注解
自定义注解类:用于注解表Table
-
package com.ann.test2;
-
-
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();
-
}
自定义注解类:用于注解Column
-
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();
-
}
注解的使用:
-
package com.ann.test2;
-
-
@Table("user")
-
public
class Filter {
-
-
@Column("id")
-
private
int id;
-
-
@Column("user_name")
-
private String userName;
-
-
@Column("nick_name")
-
private String nickName;
-
-
@Column("age")
-
private
int age;
-
-
@Column("city")
-
private String city;
-
-
@Column("email")
-
private String email;
-
-
@Column("mobile")
-
private String mobile;
-
-
public int getId() {
-
return id;
-
}
-
-
public void setId(int id) {
-
this.id = id;
-
}
-
-
public String getUserName() {
-
return userName;
-
}
-
-
public void setUserName(String userName) {
-
this.userName = userName;
-
}
-
-
public String getNickName() {
-
return nickName;
-
}
-
-
public void setNickName(String nickName) {
-
this.nickName = nickName;
-
}
-
-
public int getAge() {
-
return age;
-
}
-
-
public void setAge(int age) {
-
this.age = age;
-
}
-
-
public String getCity() {
-
return city;
-
}
-
-
public void setCity(String city) {
-
this.city = city;
-
}
-
-
public String getEmail() {
-
return email;
-
}
-
-
public void setEmail(String email) {
-
this.email = email;
-
}
-
-
public String getMobile() {
-
return mobile;
-
}
-
-
public void setMobile(String mobile) {
-
this.mobile = mobile;
-
}
-
-
}
注解解析成sql
-
package com.ann.test2;
-
-
import java.io.File;
-
import java.lang.reflect.Field;
-
import java.lang.reflect.InvocationTargetException;
-
import java.lang.reflect.Method;
-
-
public
class Test {
-
-
public static void main(String[] args) {
-
Filter filter =
new Filter();
-
filter.setId(
10);
//查询id为10的用户
-
-
Filter filter2 =
new Filter();
-
filter2.setUserName(
"lucy");
//查询用户名为lucy的用户
-
-
Filter filter3 =
new Filter();
-
filter3.setEmail(
"liu@sina.com,zh@163.com,88888@qq.com");
-
-
String sql1= query(filter);
-
String sql2= query(filter2);
-
String sql3= query(filter3);
-
-
System.out.println(sql1);
-
System.out.println(sql2);
-
System.out.println(sql3);
-
}
-
-
private static String query(Filter filter){
-
StringBuilder sb =
new StringBuilder();
-
//1.获取class
-
Class c = filter.getClass();
-
//2.获取到Table的名字
-
boolean exists = c.isAnnotationPresent(Table.class);
-
if(!exists){
-
return
null;
-
}
-
Table table = (Table) c.getAnnotation(Table.class);
-
String tableName = table.value();
-
sb.append("select * form ").append(tableName).append(" where
1=
1
");
-
//3.遍历所有的字段
-
Field[] fArray = c.getDeclaredFields();
-
for(Field f:fArray){
-
//4.处理每个字段对应的sql
-
//4.1拿到字段的名字
-
boolean fExists = f.isAnnotationPresent(Column.class);
-
if(!fExists){
-
continue;
-
}
-
Column column = f.getAnnotation(Column.class);
-
//4.2拿到字段的值
-
String columnName = column.value();
-
//获取属性的值
-
String filedName = f.getName();
-
String getMethodName = "get
"+filedName.substring(0, 1).toUpperCase()+filedName.substring(1);
-
try {
-
Method method = c.getMethod(getMethodName);
-
Object fileValue =method.invoke(filter);
-
//4.3拼接sql
-
if(fileValue==null || (fileValue instanceof Integer &&(Integer)fileValue==0)){
-
continue;
-
}
-
sb.append(" and
").append(filedName);
-
if(fileValue instanceof String){// in()
-
if(((String) fileValue).contains(",
")){
-
String[] values = ((String)fileValue).split(",
");
-
sb.append(" in (
");
-
for(String v:values){
-
sb.append("
'").append(v).append("'
").append(",
");
-
}
-
sb.deleteCharAt(sb.length()-1);
-
sb.append(")
");
-
-
}else{
-
sb.append("=
").append("
'").append(fileValue).append("'
");
-
}
-
}else if(fileValue instanceof Integer){
-
sb.append("=
").append(fileValue);
-
}
-
} catch (Exception e) {
-
e.printStackTrace();
-
}
-
}
-
return sb.toString();
-
}
-
}
结果:
select * form user where 1=1 and id=10
select * form user where 1=1 and userName='lucy'
select * form user where 1=1 and email in ('liu@sina.com','zh@163.com','88888@qq.com')
还可以参见博客:http://www.cnblogs.com/pepcod/archive/2013/02/20/2918719.html