目录
- 初识注解
- 自定义注解
- 查看某类上是否标有某注解isAnnotationPresent
- 使用自定义注解
- 解析自定义注解
- 利用注解自己实现一个简单的spring框架,实现IOC和DI
初识注解
import java.lang.annotation.*;
/**
*所有的注解默认继承自Annotation注解(本质是一个继承Annotaion的接口)
* 4个元注解(修饰注解的注解,且只能修饰注解,元注解的target=ElementType.ANNOTATION_TYPE):
* @Target @Retention @Inherited @Documented
* @Target:允许标注的位置
* ElementType.TYPE:类上
* ElementType.FIELD:属性上
* ElementType.METHOD:方法上
* @Retention:注解的保留策略(只有保留到运行时的注解才可以通过反射获取)
* RetentionPolicy.SOURCE:仅存在于源文件里(不可以通过反射读取)
* RetentionPolicy.CLASS:存在到class字节码文件里(不可以通过反射读取)
* RetentionPolicy.RUNTIME:保留到运行时候(可以通过反射读取)
* * 源代码文件---编译---》字节码文件--加载----》JVM
* * SOURCE CLASS RUNTIME
* @Inherited:注解是否可以被继承,父类标有的注解如果可继承,那么他的子类自动继承注解(接口和接
* 口实现类不支持继承注解,只支持父类和子类)
* @Documented:此注解是否能被文档所记录
*/
@Target({ElementType.TYPE, ElementType.FIELD, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface MyAnnotation {
/**
* 自定义注解用:@interface标识
* >>属性都是默认 public static final修饰(myValue)
* >>方法都是默认 public abstract修饰
* >>方法设有默认值的,使用注解不用必须指定值,没有设置默认值必须指定
* >>方法必须有返回值,但是没有参数,使用的时候直接把参数传给方法名字即可
* >>返回值必须是以下6种类型
* 1.基本数据类型
* 2.String类型
* 3.Class类型
* 4.注解类型
* 5.枚举类型
* 6.一维数组类型,但是数组内部的元素都必须是以上5种类型
**/
String myValue = "test";
int getNum();//1.基本数据类型
String name() default "";//2.String类型(有默认值)
Class<? extends UserFather> getClazz();//3.Class类型
Override getAnnotation();//4.注解类型
MyColorEnum getColorEnum();//5.枚举类型
String[] strArr();//6.一维数组类型,但是数组内部的元素都必须是以上5种类型
}
查看某类上是否标有某注解isAnnotationPresent
public class My {
public static void main(String[] args) {
Class<My1> my1Class = My1.class;
boolean annotationPresent = my1Class.isAnnotationPresent(Documented.class);
System.out.println("annotationPresent = " + annotationPresent);
}
}
自定义注解
@Target({ElementType.TYPE, ElementType.FIELD, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface MyAnnotation {
String name() default "";
String value();
}
使用自定义注解
public class User extends UserFather {
@MyAnnotation("张三")//不指定方法名:则默认是给value()方法指定的
private String userName;
private String password;
private Integer age;
@MyAnnotation(value = "张三", name = "三")
public void test() {
}
//get set .......
}
public class My {
public static void main(String[] args) {
Class<My1> my1Class = My1.class;
boolean annotationPresent = my1Class.isAnnotationPresent(Documented.class);
System.out.println("annotationPresent = " + annotationPresent);
}
}
解析自定义注解
@Test
public void test() throws ClassNotFoundException, NoSuchFieldException, NoSuchMethodException {
/**
* 解析注解值的前提是反射:
* 获取类上的注解:需要首先获取 Class--->clazz.getDeclaredAnnotation(MyAnnotation.class)
* 获取field上的注解:需要想先获取到field -->userNameField.getDeclaredAnnotation(MyAnnotation.class)
* 获取method上的注解:需要想先获取到method--->testMethod.getAnnotation(MyAnnotation.class)
* 获取到注解后直接--》注解实例.方法名就可以获取对一个方法的返回值了
*/
Class<?> clazz = Class.forName("com.blog.annotation.test.User");//获取Class
MyAnnotation classMyAnnotation = clazz.getDeclaredAnnotation(MyAnnotation.class);//获取类上的注解
System.out.println(classMyAnnotation.value());//直接调用注解里的方法获取值
System.out.println(classMyAnnotation.name());
Field userNameField = clazz.getDeclaredField("userName");
MyAnnotation fieldMyAnnotation = userNameField.getDeclaredAnnotation(MyAnnotation.class);//获取field的上的注解
System.out.println(fieldMyAnnotation.value());
System.out.println(fieldMyAnnotation.name());
Method test = clazz.getDeclaredMethod("test", null);
MyAnnotation methodMyAnnotation = test.getAnnotation(MyAnnotation.class);//获取方法上的注解
System.out.println(methodMyAnnotation.value());
System.out.println(methodMyAnnotation.name());
}
利用注解自己实现一个简单的spring框架,实现IOC和DI
(即类由代理创建,属性由代理注入)
//1.自定义注解类
@Target({ElementType.CONSTRUCTOR})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface MyAnnotation {
String[] value();
}
//2.使用注解的类
import java.util.Date;
public class User {
private String userName;
private String password;
private String age;
private User2 user2;
private Date myDate;
private Character character;
@MyAnnotation({"张三三", "admin", "14", "李四四", "20190526", "2"})
public User() {
}
get和set......
}
//3.实现IOC和DI的核心类
public class MySpring {
public Object getBeanByClassName(String name, String dateFormat) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException, ParseException {
Class<?> clazz = Class.forName(name);//获取class
Object obj = clazz.newInstance();//创建对象
Constructor<?> cons = clazz.getDeclaredConstructor();//根据class获取构造方法
MyAnnotation myAnnotation = cons.getDeclaredAnnotation(MyAnnotation.class);//获取构造方法上的注解
String[] values = myAnnotation.value();//获取注解里面的值
Field[] fields = clazz.getDeclaredFields();//获取fields
//给创建的对象属性赋值
for (int i = 0; i < fields.length; i++) {
fields[i].setAccessible(true);
Class<?> type = fields[i].getType();
if (Date.class.isAssignableFrom(type)) {//日期类型
SimpleDateFormat sdf = new SimpleDateFormat(dateFormat);
fields[i].set(obj, sdf.parse(values[i]));
} else if (Character.class.isAssignableFrom(type)) {//Character类型
char[] chars = values[i].toCharArray();
fields[i].set(obj, chars[0]);
} else {//八大包装类型)或者类对象(此对象必须有一个String类型参数的构造方法的类对象)
fields[i].set(obj, fields[i].getType().getDeclaredConstructor(String.class).newInstance(values[i]));
}
}
return obj;
}
}
//4.测试类
public class TestAnnotation {
@Test
public void test() throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, ParseException {
MySpring mySpring = new MySpring();
User user = (User) mySpring.getBeanByClassName("com.blog.annotation.test.User", "yyyyMMdd");
System.out.println(user);
}
}
//5.运行结果
{
"age":"14",
"character":"2",
"myDate":1558800000000,
"password":"admin",
"user2":{
"name":"李四四"
},
"userName":"张三三"
}
运行结果: