Это 28-й день моего участия в Gengwen Challenge.Подробности о мероприятии:Обновить вызов
Фреймворк с открытым исходным кодом Spring, который реализован с помощью аннотаций.
Фреймворк с открытым исходным кодом Spring, который полностью реализован с помощью аннотаций, мы также ощутили множество преимуществ при его использовании, поэтому нам потребуется время, чтобы увидеть использование механизма аннотаций, предоставляемого Java.
что такое аннотации
- Аннотации похожи на аннотации и играют роль в объяснении классов, методов, полей и т. д. Аннотация — это концепция, введенная после jdk1.5. Поэтому, если вы хотите реализовать аннотации, ваш jdk должен быть выше 1.5. Его можно использовать для создания документации и отслеживания зависимостей кода. Можно выполнить даже базовую проверку синтаксиса компиляции. Формат аннотации начинается с @, а имя приложения в виде @interface. Как упоминалось выше, аннотации можно понимать как аннотации, потому что аннотации не влияют на семантику кода. Аннотации существуют тремя способами: один в исходном коде, другой в компиляции, а третий действителен во время выполнения.
Роль аннотаций
- Написание документации: создавайте документацию на основе метаданных, указанных в коде.
- Анализ кода: код анализируется с помощью метаданных, идентифицированных в коде.
- Проверка компиляции: разрешите компилятору выполнять базовые проверки компиляции с помощью метаданных, указанных в коде.
Основная аннотация
- В Java мы, новички, можем не знать, что такое аннотации, но мы все должны использовать аннотации Yongfu Давайте посмотрим, где мы их использовали.
Override
- java.lang.Override — аннотация типа маркера, которая используется как метод аннотации, указывает на то, что метод является методом, унаследованным от родительского класса, то есть переопределяет одноименный метод в родительском классе. Если мы используем @override для метода, но на самом деле у родительского класса вообще нет этого метода, это означает, что наш метод не перегружает метод родительского класса. В это время мы сообщим о соответствующей ошибке компиляции при компиляции.
SuppressWarnings
- Я понимаю эту аннотацию так, что она говорит компилятору игнорировать предупреждения, которые могут появиться ниже меня. На самом деле в нем много параметров, и разные параметры выставляют разные предупреждения
- deprecation,使用了过时的类或方法时的警告
- unchecked,执行了未检查的转换时的警告
- fallthrough,当 switch 程序块直接通往下一种情况而没有 break 时的警告
- path,在类路径、源文件路径等中有不存在的路径时的警告
- serial,当在可序列化的类上缺少serialVersionUID 定义时的警告
- finally ,任何 finally 子句不能正常完成时的警告
- all,关于以上所有情况的警告
Deprecated
- Я эту аннотацию на самом деле не трогал, я искал это в Интернете, и они объяснили это как
Его роль заключается в добавлении аннотаций к методам, которые больше не должны использоваться. Когда программисты используют эти методы, во время компиляции будет отображаться подсказка. Он имеет ту же функцию, что и тег @deprecated в javadoc. Точнее, он также не так же хорошо, как javadoc @deprecated, поскольку он не поддерживает параметры, пример кода с использованием @Deprecated выглядит следующим образом:
- Когда мы обычно пишем код и используем методы в jdk, иногда мы сталкиваемся с методом, который устарел, но его можно использовать.Этот метод реализуется через эту аннотацию.Короче говоря, это напоминает разработчикам, что метод устарел, и попробуйте избегать использования устаревших методов.
jdk предоставляет способ разработки аннотаций
- С приведенным выше введением у нас есть более или менее понимание аннотаций.Поскольку в Java уже есть концепция аннотаций, как мы разрабатываем наши собственные аннотации? В пакете java.lang.annotation jdk размещает аннотации об аннотациях, то есть через классы аннотаций внутри мы можем разрабатывать собственные аннотации. Давайте сначала разберемся с аннотациями аннотаций.
- Судя по исходному коду, четыре класса исключений: annotation, annotationFormatError, annotationTypeMismatchExcetion и IncompleteAnnotationException являются базовыми классами форматирования страничной игры. Мы не столкнемся с этими классами при разработке аннотаций, но все они являются логикой в jdk. Что мы действительно используем, так это оставшиеся несколько классов.
ElementType
- Этот класс является перечислением, и перечисленные здесь поля используются в классе Target. Специально описано в Target
RetentionPolicy
- Этот класс является перечислением, и перечисленные здесь поля используются в классе Retention. В частности, объяснено в разделе «Удержание»
Documented
/**
* Indicates that annotations with a type are to be documented by javadoc
* and similar tools by default. This type should be used to annotate the
* declarations of types whose annotations affect the use of annotated
* elements by their clients. If a type declaration is annotated with
* Documented, its annotations become part of the public API
* of the annotated elements.
*
* @author Joshua Bloch
* @since 1.5
*/
- Это описание задокументированного класса на jdk официального сайта, Общий смысл этого описания в том, что объявление этого класса является аннотацией, используемой для генерации документов Java, то есть описание документа может быть сгенерировано на эту аннотацию, и это также по умолчанию Utilities. Эта аннотация должна быть внедрена на клиенте. В то же время их методы также становятся общедоступными API.
Target
/**
* Indicates the kinds of program element to which an annotation type
* is applicable. If a Target meta-annotation is not present on an
* annotation type declaration, the declared type may be used on any
* program element. If such a meta-annotation is present, the compiler
* will enforce the specified usage restriction.
*
* For example, this meta-annotation indicates that the declared type is
* itself a meta-annotation type. It can only be used on annotation type
* declarations:
* <pre>
* @Target(ElementType.ANNOTATION_TYPE)
* public @interface MetaAnnotationType {
* ...
* }
* </pre>
* This meta-annotation indicates that the declared type is intended solely
* for use as a member type in complex annotation type declarations. It
* cannot be used to annotate anything directly:
* <pre>
* @Target({})
* public @interface MemberType {
* ...
* }
* </pre>
* It is a compile-time error for a single ElementType constant to
* appear more than once in a Target annotation. For example, the
* following meta-annotation is illegal:
* <pre>
* @Target({ElementType.FIELD, ElementType.METHOD, ElementType.FIELD})
* public @interface Bogus {
* ...
* }
* </pre>
*/
-
Вышеприведенное по-прежнему является описанием на официальном сайте Java JDK. Прежде всего, если элемент типа, указанный целью, не существует, то аннотация, указанная целью, может использоваться где угодно. Если цель указывает элемент, аннотация должна использоваться только в указанном элементе.На элементе цели элемент, указанный целью, определяется классом перечисления ElementType, а перечисление внутри является значением, которое может указать цель. Список на официальном сайте — Target(ElementType.ANNOTATION_TYPE), указывающий, что эту аннотацию можно использовать только в провинции аннотаций. Есть еще одно свойство, которого нет в перечислении ElementType, а именно
target({}), то есть аннотация через {} используется в переменной-члене, отвечающей за аннотацию, и ее нельзя использовать в других местах. -
ElementType.CONSTRUCTOR: используется для описания конструктора.
-
ElementType.FIELD: переменные-члены, объекты, свойства (включая экземпляры перечисления)
-
ElementType.LOCAL_VARIABLE: используется для описания локальных переменных.
-
ElementType.METHOD: используется для описания метода
-
ElementType.PACKAGE: используется для описания пакета
-
ElementType.PARAMETER: используется для описания параметров
-
ElementType.TYPE: используется для описания классов, интерфейсов (включая типы аннотаций) или объявлений перечисления.
Retention
/**
* Indicates how long annotations with the annotated type are to
* be retained. If no Retention annotation is present on
* an annotation type declaration, the retention policy defaults to
* {@code RetentionPolicy.CLASS}.
*
* <p>A Retention meta-annotation has effect only if the
* meta-annotated type is used directly for annotation. It has no
* effect if the meta-annotated type is used as a member type in
* another annotation type.
*
* @author Joshua Bloch
* @since 1.5
*/
-
Атрибуты этого класса перечисляются через класс перечисления RetentionPolicy, основная функция которого заключается в указании времени существования нашей аннотации или момента ее существования. Этот атрибут действителен только при использовании непосредственно в аннотациях исходного типа аннотаций. Это не имеет никакого эффекта, если используется для переменных-членов других аннотаций.
-
RetentionPolicy.SOURCE : отбрасывается во время компиляции. Эти аннотации больше не имеют никакого значения после компиляции, поэтому они не записываются в байт-код. @Override, @SuppressWarnings относятся к этому типу аннотаций.
-
RetentionPolicy.CLASS: отбрасывается при загрузке класса. Полезно при обработке файлов байт-кода. Аннотации используют этот метод по умолчанию
- RetentionPolicy.RUNTIME : 始终不会丢弃,运行期也保留该注解,因此可以使用反射机制读取该注解的信息。我们自定义的注解通常使用这种方式。
Inherited
/**
* Indicates that an annotation type is automatically inherited. If
* an Inherited meta-annotation is present on an annotation type
* declaration, and the user queries the annotation type on a class
* declaration, and the class declaration has no annotation for this type,
* then the class's superclass will automatically be queried for the
* annotation type. This process will be repeated until an annotation for this
* type is found, or the top of the class hierarchy (Object)
* is reached. If no superclass has an annotation for this type, then
* the query will indicate that the class in question has no such annotation.
*
* <p>Note that this meta-annotation type has no effect if the annotated
* type is used to annotate anything other than a class. Note also
* that this meta-annotation only causes annotations to be inherited
* from superclasses; annotations on implemented interfaces have no
* effect.
*
* @author Joshua Bloch
* @since 1.5
*/
- Резюме одного предложения: разрешить ли подклассам наследовать аннотацию.
пользовательская аннотация
- Так много было сказано выше, поэтому давайте приступим к разработке собственных аннотаций.
Аннотация конструктора
/**
* 该注解用于doc文档
* 该注解用于类的构造函数的注解
* 该注解尽在运行期间有效
* @author xinhua
*
*/
@Documented
@Target(ElementType.CONSTRUCTOR)
@Retention(RetentionPolicy.RUNTIME)
public @interface ConstructorAnno
{
String decs() default "我是描述构造函数的注解";
}
аннотация поля
/**
* 该注解用于生成doc文档
* 该注解用于在类的字段属性上的注解
* 该注解尽在运行期间有效
* @author xinhua
*
*/
@Documented
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface FieldAnno
{
String desc() default "我是描述字段的注解";
}
аннотация локальной переменной
/**
* 该注解用于生成doc文档
* 该注解用于在局部变量上的注解
* 该注解尽在运行期间有效
* @author xinhua
*
*/
@Documented
@Target(ElementType.LOCAL_VARIABLE)
@Retention(RetentionPolicy.RUNTIME)
public @interface LocalAnno
{
String desc() default "我是描述一个局部变量的注解";
}
аннотация метода
/**
* 这个注解用于生成doc文档
* 这个注解用于类的方法上的注解
* 这个注解尽在运行期间有效
* @author xinhua
*
*/
@Documented
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MethodAnno
{
//默认提交时间 2017-2-28
String time() default "2017-2-28";
//默认 男 true 男 false 女
boolean sex() default true;
}
аннотация пакета
/**
* 该注解用于生成doc文档
* 该注解用于在包的注解
* 该注解尽在运行期间有效
* @author xinhua
*
*/
@Documented
@Target(ElementType.PACKAGE)
@Retention(RetentionPolicy.RUNTIME)
public @interface PackageAnno
{
String desc() default "我是描述包的注解";
}
аннотация параметра
/**
* 该注解用于doc文档的生成
* 该注解用于类的参数中
* 该注解尽在运行期间有效
* @author xinhua
*
*/
@Documented
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
public @interface StuInfo
{
String value() default "";
}
введите аннотацию
/**
* 该注解用于生活曾doc文档
* 该注解用于在类的注解
* 该注解尽在运行期间有效
* @author xinhua
*
*/
@Documented
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface TypeAnno
{
String desc() default "我是描述类型的注解";
}
Класс Entity добавлен в тест
/**
* 测试所有类型的注解的作用
* @author xinhua
*
*/
public @TypeAnno(desc="我是普通类")class User
{
@FieldAnno
private String UID;
@FieldAnno(desc="我是UserName的")
private String userName;
@ConstructorAnno
public User(){
}
@MethodAnno(time="2015-12-8" , sex=false)
public void doHomeWork(@StuInfo(value="211311084") String UID, @StuInfo(value="张新华")String UserName){
@LocalAnno(desc="flag的局部变量")boolean flag;
}
}
Добавить тестовый класс интерфейса
public interface UserImp
{
public void DoHouseWork(@StuInfo(value="我是小学生")String stuType,@StuInfo(value="我在大扫除")String things);
}
тестовая аннотация
/**
* 开始通过反射获取注解内容
* @author xinhua
*
*/
public class Junit
{
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, SecurityException
{
Class<?> userClass = Class.forName("tom.change.annotation.User");
//实例化
Object userObject = userClass.newInstance();
//1--获取最外层的就是类的注解 TypeAnno
System.out.println(".......................类注解.......................");
TypeAnno typeAnno= userClass.getAnnotation(TypeAnno.class);
System.out.println(typeAnno.desc());
//2--获取字段注解 首先获取通过反射获取类中的属性字段
System.out.println(".......................字段注解.......................");
Field[] fields = userClass.getDeclaredFields();
for (Field field : fields)
{
FieldAnno fieldAnno = field.getAnnotation(FieldAnno.class);
System.out.println(fieldAnno.desc());
}
//3-- 方法的注解
System.out.println(".......................方法注解.......................");
Method method = userClass.getMethod("doHomeWork", String.class,String.class);
MethodAnno methodAnno = method.getAnnotation(MethodAnno.class);
System.out.println(methodAnno.time()+"@@@"+methodAnno.sex());
//4-- 参数的注解 动态代理方式实现参数
System.out.println(".......................参数注解.......................");
UserImp userImp=getMethodParameter(UserImp.class);
userImp.DoHouseWork("张新华", "--》扫地");
//5--局部变量注解
System.out.println(".......................局部变量注解.......................");
//赞未获得到
}
public static<T> T getMethodParameter(Class<T> target){
return (T)Proxy.newProxyInstance(target.getClassLoader(), new Class<?>[]{target}, new InvocationHandler()
{
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable
{
Annotation[][] parameterAnnotations = method.getParameterAnnotations();
for (int i=0;i<parameterAnnotations.length;i++)
{
Annotation[] annotations=parameterAnnotations[i];
StuInfo stuInfo =(StuInfo) annotations[0];
System.out.println(stuInfo.value()+"@@@"+args[i]);
}
return null;
}
});
}
}