精华内容
下载资源
问答
  • 使用Spring aop实现一个小例子,依赖注入使用注解实现,但是总是报错,信息如下:严重: Caught exception while allowing TestExecutionListener [org.springframework.test.context.support.... to pre...

    使用Spring aop实现一个小例子,依赖注入使用注解实现,但是总是报错,信息如下:

    严重: Caught exception while allowing TestExecutionListener [org.springframework.test.context.support.DependencyInjectionTestExecutionListener@4df828d7] to prepare test instance [com.zkzong.springinaction.springidol.AopAnnoTest@5e01a982]

    org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'com.zkzong.springinaction.springidol.AopAnnoTest': Unsatisfied dependency expressed through field 'performer': Bean named 'instrumentalistAnno' is expected to be of type [com.zkzong.springinaction.springidol.InstrumentalistAnno] but was actually of type [com.sun.proxy.$Proxy15]; nested exception is org.springframework.beans.factory.BeanNotOfRequiredTypeException: Bean named 'instrumentalistAnno' is expected to be of type [com.zkzong.springinaction.springidol.InstrumentalistAnno] but was actually of type [com.sun.proxy.$Proxy15]

    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:569)

    at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:88)

    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:349)

    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1214)

    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireBeanProperties(AbstractAutowireCapableBeanFactory.java:385)

    at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:118)

    at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:83)

    展开全文
  • 鼠标放在方法名上后显示让我们去掉 @override 注解,如图:原因:@Override 是 jdk5 引入的机制,但是不支持对接口的实现。认为这不是 override 而报错,jdk6 及1.6以上的版本修正了这个 bug,无论是对父类的方法...

    错误:

    在 eclipse 的新工作空间开发项目时,出现大面积方法编译错误。鼠标放在方法名上后显示让我们去掉 @override 注解,如图:

    41400116ba4b1fd226d5bbcf254a9817.png

    原因:

    @Override 是 jdk5 引入的机制,但是不支持对接口的实现。认为这不是 override 而报错,jdk6 及1.6以上的版本修正了这个 bug,无论是对父类的方法覆盖还是对接口的实现都可加上 @Override。

    解决:

    1. 删除 @Override 注解。该方法工作量太大,而且这也不是从根本上解决问题。

    2. 首先要确保机器上安装了 jdk 1.6 或以上版本,

    选择 eclipse 菜单 Windows->Preferences-->java->Compiler-->compiler compliance level 选择 1.6 或以上版本,刷新工程,重新编译。

    6a612fa2ad9cc858c05b887a6cae682e.png

    另外也可以针对性的在项目上,鼠标右键选择 Properties-->Java Compiler-->compiler compliance level 中选择 1.6 或以上,刷新工程,重新编译。

    展开全文
  • 关于 Java注解预处理的资料实在是过于稀少,连stackoverflow上都没多少人研究,以致于我这个萌新在尝试使用注解预处理来生成代码时踩了不少坑,正好博客也快长草了,遂决定留一篇文章,希望能够对后来者有所帮助...

    关于 Java 的注解预处理的资料实在是过于稀少,连stackoverflow上都没多少人研究,以致于我这个萌新在尝试使用注解预处理来生成代码时踩了不少坑,正好博客也快长草了,遂决定留一篇文章,希望能够对后来者有所帮助。

    本文章同时对一般 Java 项目和 Android 项目适用。

    为何使用 Java 注解预处理

    诚然,用反射处理注解来替代代码的复制粘贴可以让代码更加简洁、易懂(优雅),但是,反射实在是太 慢

    了。

    啥?反射不慢?来来来,一个 Activity 就用几十次反射,要不要和复制粘贴做一下对比?(手动阴险)

    那反射这么慢,有没有什么办法?当然就是今天的主题了——代码生成: 让编译器来给你“复制粘贴”,既优雅,又高效(反正生成的代码你也不看)。

    如何使用 Java 注解预处理

    关于注解预处理的基本使用方法的资料还是很多的,这里就不细说了,概括一下就是:

    javax.annotation.processing.AbstractProcessor

    META-INF.services.javax.annotation.processing.Processor

    注意:对于 Android 项目,你需要单独建立一个 “Java 类” 项目,不可以直接在原 Android 项目中使用 注解预处理,否则你会发现没有 javax 这个包。

    然后,在 Android 项目的 build.gradle

    中的 dependencies

    添加 annotationProcessor project(':项目名')

    处理我们的注解

    假定我们要处理的注解名为 ViewAutoLoad

    ,定义为:

    @Retention(RetentionPolicy.CLASS) //保留此注解到编译期

    @Target(ElementType.FIELD) //此注解只适用于“字段”

    public @interface ViewAutoLoad {

    }

    本文通过介绍对字段注解的处理来讲述如何实现注解预处理,对于方法,用法其实没啥区别。

    然后,重写 process

    方法:

    @Override

    public boolean process(Set extends TypeElement> annotations, RoundEnvironment roundEnv) {

    return true;

    }

    为啥要留个 return true

    ? true表示这个注解已经被我们处理过了,编译器不用再调用其他注解处理器了。

    然后开始写我们的处理代码,这里就有两种处理注解的办法了:

    办法1:一次性全局处理注解

    这种方法 不能

    知道这个字段(方法)到底是哪个类的,自然也不能获取除了你正在处理的字段(方法)所在类的其他信息,但是用起来方便一些。

    获取 全局所有

    具有此注解的字段,然后用 processAnnotation

    方法逐一处理它们:

    roundEnv.getElementsAnnotatedWith(ViewAutoLoad.class).forEach(this::processAnnotation);

    这里先讲一些常用操作,假定我们现在在实现上文的 processAnnotation

    方法,它的方法签名为:

    private void processFormNotEmpty(Element annotatedElement)

    获取字段的类型

    如果你将来要生成代码或者将注解用作编译时检查,十有八九要用到这个字段的类型。

    TypeMirror fieldType = annotatedElement.asType();

    获取这个字段的注解,或者注解的值

    ViewAutoLoad annotation = annotatedElement.getAnnotation(ViewAutoLoad.class);

    现在,你可以直接使用你在注解接口定义的方法了,虽然作为示例的 ViewAutoLoad

    没定义任何方法。

    假装定义了 value()

    : annotation.value()

    获取这个字段(方法)的名字

    我觉得这个肯定会用吧

    Name fieldVarName = annotatedElement.getSimpleName();

    //string: fieldVarName.toString();

    获取这个方法的修饰符

    annotatedElement.getModifiers()

    返回一个集合,这个集合装着 javax.lang.model.element.Modifier

    这个枚举

    办法2:逐类处理注解

    虽然麻烦了点,但是这个办法让我们可以知道我们在处理哪个类了。

    我们回到 process

    方法:

    Set extends Element> rootElements = roundEnv.getRootElements();

    这次我们直接拿到所有编译器处理的类的基础信息了,嗯,没有过滤器。

    现在我们得手撸过滤器了,既然是 Set,先遍历走起。

    然后怎么过滤呢?这里有一些思路:

    给字段(方法)上注解的时候就指定好这个类的名称,比如 @Example("com.kenvix.test.TestClass")

    注意:不要指定成 TestClass.class

    ,在编译期无法这样读取类名,因为类尚未编译。

    遍历所有类,通过字段(方法)的一些特征查找这个类

    第一种思路

    第一种可以是十分简单粗暴了。

    String targetName = "com.kenvix.test.TestClass";

    Element targetClass = null;

    for (Element element : rootElements) {

    if(element.toString().equals(targetName)) {

    targetClass = element;

    break;

    }

    }

    //这里只拿到了类,注解处理方法暂时省略,见下文。

    第二种思路

    显然,第一种实在是不怎么优雅,第二种方法又有这些思路:

    android.*

    Map> tasks = new HashMap<>();

    for (Element classElement : rootElements) {

    if(classElement.toString().startsWith(Environment.TargetAppPackage)) {

    List extends Element> enclosedElements = classElement.getEnclosedElements();

    for(Element enclosedElement : enclosedElements) {

    List extends AnnotationMirror> annotationMirrors = enclosedElement.getAnnotationMirrors();

    for (AnnotationMirror annotationMirror : annotationMirrors) {

    if(ViewAutoLoad.class.getName().equals(annotationMirror.getAnnotationType().toString())) { //好像没有其他办法在这里判断是否是目标注解了

    if(!tasks.containsKey(classElement))

    tasks.put(classElement, new LinkedList<>());

    tasks.get(classElement).add(enclosedElement);

    }

    }

    }

    }

    }

    这样,这个 Map<> 中就包含了我们需要的类和这个类持有的字段了,接下来进行处理即可

    嗯?效率低?这是编译期,加钱换CPU或用第一种,请(手动滑稽)

    生成代码

    这里需要用到 javapoet 这个依赖,编辑gradle配置,加入依赖:

    implementation 'com.squareup:javapoet:1.8.0'

    然后重写 init 方法:

    protected Types typeUtil;

    protected Elements elementUtil;

    protected Filer filer;

    protected Messager messager;

    protected ProcessingEnvironment processingEnv;

    @Override

    public synchronized final void init(ProcessingEnvironment processingEnv) {

    super.init(processingEnv);

    this.processingEnv = processingEnv;

    typeUtil = processingEnv.getTypeUtils();

    elementUtil = processingEnv.getElementUtils();

    filer = processingEnv.getFiler();

    messager = processingEnv.getMessager();

    onPreprocessorInit();

    messager.printMessage(Diagnostic.Kind.NOTE, "Preprocessor: " + this.getClass().getSimpleName() + " Initialized");

    }

    回到 process 方法,刚才我们已经拿到了要处理的注解,接下来开始处理这些注解:

    JavaPoet 资料到处都是啊,要写还不容易?

    我咋取一个不可能导入的包的类型?

    这问题还是很常见的,比如我们没法在一个 Java 项目中用 Android 包的东西,但是却需要生成相关的代码.

    例如,我们需要用到一个类 AppCompatActivity,它在 android.support.v7.app

    这个包,则可以这样写:

    ClassName appCompatClass = ClassName.get("android.support.v7.app", "AppCompatActivity");

    我咋表示类型通配符、泛型限定?

    接上,我们还想表示 ? extends AppCompatActivity

    ,可以这样写:

    MethodSpec.Builder builder = code; //这里是你的方法builder

    builder.addTypeVariable(TypeVariableName.get("T", appCompatClass)).addParameter(TypeVariableName.get("T"), "target")

    保存我们的生成的代码,并在下一步编译生成的代码

    回到 process 方法,加上:

    if(roundEnv.processingOver()) {

    //创建FormChecker这个类

    TypeSpec formChecker = TypeSpec.classBuilder("FormChecker")

    .addModifiers(Modifier.PUBLIC, Modifier.FINAL)

    .addMethods(methods)

    .build();

    //创建类文件

    JavaFile javaFile = JavaFile.builder("com.kenvix.eg.generated", formChecker)

    .addFileComment(getFileHeader())

    .build();

    try {

    javaFile.writeTo(filer);

    } catch (IOException ex) {

    throw new IllegalStateException(ex.toString());

    }

    }

    对同一个 javaFile

    , javaFile.writeTo(filer)

    只能调用一次,故需要判断是否为最后一轮注解预处理。

    其他的可以看看 这篇文章

    ,虽然标题挺扯的(够你:horse:)

    其他小问题

    我咋调试啊

    显然这个时候按 IDE 的断点按钮是莫得了。

    直接 System.out

    或 Logger

    也不太好,分分钟被一堆垃圾编译消息淹没。用着还麻烦。

    好吧,其实有个简单粗暴的方法,抛个运行时异常嘛,这样就能直接停止编译然后让 IDE 显示我们想要的东西了。

    throw new IllegalStateException("something");

    IDEA 对 addModifiers(), javaFile.writeTo(filer) 报错

    IDEA bug

    别理他,编译就行了

    展开全文
  • 开幕:初见首先看一下家喻户晓的@Override注解:添加此注解,如果是非覆写的方法,就会报错@Target(ElementType.METHOD)@Retention(RetentionPolicy.SOURCE)public @interface Override {}再先看一下@Deprecated注解...

    开幕:初见

    首先看一下家喻户晓的@Override注解:添加此注解,如果是非覆写的方法,就会报错

    @Target(ElementType.METHOD)

    @Retention(RetentionPolicy.SOURCE)

    public @interface Override {

    }

    再先看一下@Deprecated注解:添加此注解,如果是过时的方法,就会画线提示

    @Documented

    @Retention(RetentionPolicy.RUNTIME)

    @Target(value={CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE, MODULE, PARAMETER, TYPE})

    public @interface Deprecated {

    String since() default "";

    boolean forRemoval() default false;

    }

    我们这个群体应该很擅长归纳事物的共性,然后总结出一丝规律

    可以看到的是:

    public @interface 注解名{

    }

    因此,可依照这样自己写一个注解类:

    public @interface APerson {

    }

    然后新建一个Person类看看能不能用:

    @APerson

    public class Person {

    }

    编译器没报错,看了可以,于是你的第一个没用的注解就由此诞生,开幕止。

    第一幕:相识:

    原标签

    1:@Retention(注解存活期):接受一个RetentionPolicy类型的枚举常量

    //源码的RetentionPolicy枚举

    public enum RetentionPolicy {

    /**

    * Annotations are to be discarded by the compiler.

    * 注解将会被编译器删除

    */

    SOURCE,

    /**

    * Annotations are to be recorded in the class file by the compiler

    * but need not be retained by the VM at run time. This is the default

    * behavior.

    * 编译器会将注解保留在字节码文件中,但VM会再运行期间保留它。这是默认行为

    */

    CLASS,

    /**

    * Annotations are to be recorded in the class file by the compiler and

    * retained by the VM at run time, so they may be read reflectively.

    * 编译器会将注解保留在字节码文件中,VM也会在运行期间保留它。(所以他们可以通过反射性被读取)

    *@see java.lang.reflect.AnnotatedElement

    */

    RUNTIME

    }

    创建一个运行期的注解

    @Retention(RetentionPolicy.RUNTIME)

    public @interface APerson {

    }

    2:@Target(目标):接受一个ElementType类型的枚举常量

    //源码枚举类:ElementType

    public enum ElementType {

    /** Class, interface (including annotation type), or enum declaration */

    //声明类,接口(包括注解类型),或者枚举

    TYPE,

    /** Field declaration (includes enum constants) */

    //声明字段(包括枚举常量)

    FIELD,

    /** Method declaration */

    //声明方法

    METHOD,

    /** Formal parameter declaration */

    //声明方法参数

    PARAMETER,

    /** Constructor declaration */

    //声明构造函数

    CONSTRUCTOR,

    /** Local variable declaration */

    //声明局部变量

    LOCAL_VARIABLE,

    /** Annotation type declaration */

    //声明注解

    ANNOTATION_TYPE,

    /** Package declaration */

    //声明包

    PACKAGE,

    /**

    * Type parameter declaration

    * 声明参数类型

    *@since 1.8

    */

    TYPE_PARAMETER,

    /**

    * Use of a type

    *

    *@since 1.8

    */

    TYPE_USE,

    /**

    * Module declaration.

    * 声明模块

    *@since 9

    */

    MODULE

    }

    3:@Inherited(继承):子类继承父类的注解

    4:@Repeatable(可重复)

    5:@Documented:能够将注解中的元素包含到 Javadoc。

    已经同注解进行了基本的对话(了解),第二幕止。

    第三幕:交涉

    改善一下我们的注解

    package top.toly.注解;

    import java.lang.annotation.*;

    /**

    * 作者:张风捷特烈

    * 时间:2018/5/22:8:20

    * 邮箱:1981462002@qq.com

    * 说明:注解类

    */

    @Retention(RetentionPolicy.RUNTIME)

    @Target(ElementType.TYPE)

    public @interface APerson {

    public String name() default "捷特";

    public int age() default 24;

    }

    使用反射获取APerson对象,再得到其方法

    package top.toly.注解;

    /**

    * 作者:张风捷特烈

    * 时间:2018/5/22:8:21

    * 邮箱:1981462002@qq.com

    * 说明:注解测试端

    */

    @APerson(name = "捷特", age = 24)

    public class Person {

    APerson aPerson = getClass().getAnnotation(APerson.class);

    public void say() {

    String name = aPerson.name();

    int age = aPerson.age();

    System.out.println("my name is "+name+",and I am "+age+"years old");

    }

    public static void main(String[] args) {

    Person person = new Person();

    person.say();

    }

    }

    输出结果

    my name is 捷特,and I am 24 years old.

    现在测试一下@Inherited(继承):

    package top.toly.注解;

    /**

    * 作者:张风捷特烈

    * 时间:2018/5/22:8:21

    * 邮箱:1981462002@qq.com

    * 说明:注解测试端

    */

    @APerson(name = "捷特", age = 24)

    public class Person {

    APerson aPerson = getClass().getAnnotation(APerson.class);

    public void say() {

    String name = aPerson.name();

    int age = aPerson.age();

    System.out.println("my name is "+name+",and I am "+age+" years old.");

    }

    public static void main(String[] args) {

    Student student = new Student();

    student.say();

    }

    }

    class Student extends Person {

    }

    运行:报错

    Exception in thread "main" java.lang.NullPointerException

    at top.toly.注解.Person.say(Person.java:14)

    at top.toly.注解.Person.main(Person.java:22)

    添加@Inherited注解

    @Retention(RetentionPolicy.RUNTIME)

    @Target(ElementType.TYPE)

    @Inherited

    public @interface APerson {

    public String name() default "捷特";

    public int age() default 24;

    }

    运行:

    //

    my name is 捷特,and I am 24 years old.

    这时你已经可以通过注解来获取信息了

    第四幕:共鸣

    人类创造了刀,有些人用它雕精美的艺术品,有人依靠它成为江湖浪客,有人以它护生,有人用它杀生。

    成败善恶并非工具的荣辱,也非是锻造它的人,一切只取决于握刀人的本性与技艺。

    下面通过两个简单示例实战一下

    package top.toly.注解;

    import java.lang.annotation.Retention;

    import java.lang.annotation.RetentionPolicy;

    /**

    * 作者:张风捷特烈

    * 时间:2018/5/22:10:16

    * 邮箱:1981462002@qq.com

    * 说明:注解类

    */

    @Retention(RetentionPolicy.RUNTIME)

    public @interface ADebug {

    }

    package top.toly.注解;

    import java.lang.reflect.Method;

    /**

    * 作者:张风捷特烈

    * 时间:2018/5/22:10:17

    * 邮箱:1981462002@qq.com

    * 说明:测试工具类

    */

    public class Debug {

    public static void debug(String clazz_name) {

    Class> clazz = null;//获取测试类字节码文件

    Object testobj = null;//通过字节码获取实例

    try {

    clazz = Class.forName(clazz_name);

    testobj = clazz.newInstance();

    } catch (Exception e) {

    e.printStackTrace();

    }

    Method[] method = clazz.getDeclaredMethods();//通过字节码获取所有方法

    //用来记录测试产生的 log 信息

    StringBuilder log = new StringBuilder();

    // 记录异常的次数

    int errornum = 0;

    for (Method m : method) {

    // 只有被 @ADebug 标注过的方法才进行测试

    if (m.isAnnotationPresent(ADebug.class)) {

    try {

    m.setAccessible(true);

    m.invoke(testobj, null);//执行方法

    } catch (Exception e) {

    errornum++;

    log.append("错误"+errornum+":"+m.getName()+"() has error:");

    log.append("\n\r caused by ");

    //记录测试过程中,发生的异常的名称

    log.append(e.getCause().getClass().getSimpleName());

    log.append("\n\r");

    //记录测试过程中,发生的异常的具体信息

    log.append(e.getCause().getMessage());

    log.append("\n\r");

    }

    }

    }

    log.append(clazz.getSimpleName());

    log.append(" has ");

    log.append(errornum);

    log.append(" error.");

    // 生成测试报告

    System.out.println(log.toString());

    }

    }

    package top.toly.注解;

    /**

    * 作者:张风捷特烈

    * 时间:2018/5/22:10:18

    * 邮箱:1981462002@qq.com

    * 说明:待测试类

    */

    public class BugTest {

    @ADebug

    public void say(){

    System.out.println(Integer.parseInt("a"));

    }

    @ADebug

    public void jia(){

    System.out.println("1+1="+1+1);

    }

    @ADebug

    public void jian(){

    System.out.println("1-1="+(1-1));

    }

    @ADebug

    public void cheng(){

    System.out.println("3 x 5="+ 3*5);

    }

    @ADebug

    public void chu(){

    System.out.println("6 / 0="+ 6 / 0);

    }

    public void resay(){

    say();

    }

    }

    package top.toly.注解;

    /**

    * 作者:张风捷特烈

    * 时间:2018/5/22:10:28

    * 邮箱:1981462002@qq.com

    * 说明:运行端

    */

    public class Client {

    public static void main(String[] args) {

    Debug.debug("top.toly.注解.BugTest");

    }

    }

    输出:

    1-1=0

    3 x 5=15

    1+1=11

    错误1:say() has error:

    caused by NumberFormatException

    For input string: "a"

    错误2:chu() has error:

    caused by ArithmeticException

    / by zero

    BugTest has 2 error.

    可以看到未加注解的方法,即使错了也不会检查到。

    注解更像提示你一下到这要不要做些什么事,具体逻辑还需要具体的类来实现。

    唯一的优势在于你知道了程序已经运行到注解处,还有你可以获取到注解中的字段值。

    示例二:根据一个bean对象,来输处MySQL的查询语句

    1.数据库列(字段)注解

    package top.toly.注解.test;

    import java.lang.annotation.ElementType;

    import java.lang.annotation.Retention;

    import java.lang.annotation.RetentionPolicy;

    import java.lang.annotation.Target;

    /**

    * 作者:张风捷特烈

    * 时间:2018/5/22:23:27

    * 邮箱:1981462002@qq.com

    * 说明:数据库列(字段)注解

    */

    @Target(ElementType.FIELD)

    @Retention(RetentionPolicy.RUNTIME)

    public @interface Column {

    String value();

    }

    2.数据库表注解

    package top.toly.注解.test;

    import java.lang.annotation.ElementType;

    import java.lang.annotation.Retention;

    import java.lang.annotation.RetentionPolicy;

    import java.lang.annotation.Target;

    /**

    * 作者:张风捷特烈

    * 时间:2018/5/22:23:27

    * 邮箱:1981462002@qq.com

    * 说明:数据库表注解

    */

    @Target(ElementType.TYPE)

    @Retention(RetentionPolicy.RUNTIME)

    public @interface Table {

    String value();

    }

    3.bean对象Sworld:曾经创建过一个sword的数据库,正好拿来用。(对MySQL不熟悉的可以看我的MySQL篇)

    package top.toly.注解.test.bean;

    import top.toly.注解.test.Column;

    import top.toly.注解.test.Table;

    /**

    * 作者:张风捷特烈

    * 时间:2018/5/23:14:47

    * 邮箱:1981462002@qq.com

    * 说明:

    */

    @Table("sword")

    public class Sword {

    @Column("id")

    private int id;

    @Column("name")

    private String name;

    @Column("atk")

    private int atk;

    @Column("hit")

    private int hit;

    @Column("crit")

    private int crit;

    @Column("attr_id")

    private int attr_id;

    @Column("type_id")

    private int type_id;

    public int getId() {

    return id;

    }

    public void setId(int id) {

    this.id = id;

    }

    public String getName() {

    return name;

    }

    public void setName(String name) {

    this.name = name;

    }

    public int getAtk() {

    return atk;

    }

    public void setAtk(int atk) {

    this.atk = atk;

    }

    public int getHit() {

    return hit;

    }

    public void setHit(int hit) {

    this.hit = hit;

    }

    public int getCrit() {

    return crit;

    }

    public void setCrit(int crit) {

    this.crit = crit;

    }

    public int getAttr_id() {

    return attr_id;

    }

    public void setAttr_id(int attr_id) {

    this.attr_id = attr_id;

    }

    public int getType_id() {

    return type_id;

    }

    public void setType_id(int type_id) {

    this.type_id = type_id;

    }

    }

    4.核心类:QueryUtil:使用注解辅助得到查询语句

    package top.toly.注解.test;

    import java.lang.reflect.Field;

    import java.lang.reflect.Method;

    /**

    * 作者:张风捷特烈

    * 时间:2018/5/23:14:53

    * 邮箱:1981462002@qq.com

    * 说明:使用注解辅助得到查询语句

    */

    public class QueryUtil {

    public static String query(Object o) {

    StringBuffer sb = new StringBuffer();

    //1.获取class

    Class> aClass = o.getClass();

    //2.获取表名

    boolean exist = aClass.isAnnotationPresent(Table.class);

    if (exist) {

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

    String tableName = table.value();

    sb.append("SELECT * FROM ").append(tableName).append(" WHERE 1=1");

    //3.遍历字段

    Field[] fields = aClass.getDeclaredFields();

    for (Field field : fields) {

    //4.处理字段对应的sql

    boolean b = field.isAnnotationPresent(Column.class);

    if (!b) {

    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);

    Object fieldValue = null;

    try {

    Method getMethod = aClass.getMethod(getMethodName);

    fieldValue = getMethod.invoke(o);

    } catch (Exception e) {

    e.printStackTrace();

    }

    //拼装sql

    if (fieldValue == null || (fieldValue instanceof Integer && (Integer) fieldValue == 0)) {

    continue;

    }

    sb.append(" and ").append(fieldName);

    if (fieldValue instanceof String) {

    String value = (String) fieldValue;

    if (value.contains(",")) {

    String[] strings = value.split(",");

    sb.append(" in(");

    for (String string : strings) {

    sb.append("'").append(string).append("'").append(",");

    }

    sb.deleteCharAt(sb.length() - 1);

    sb.append(")");

    }else {

    sb.append("=").append("'" + fieldValue + "'");

    }

    }else {

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

    }

    }

    }

    return sb.toString();

    }

    }

    5.测试端

    package top.toly.注解.test;

    import top.toly.注解.test.bean.Sword;

    /**

    * 作者:张风捷特烈

    * 时间:2018/5/23:14:54

    * 邮箱:1981462002@qq.com

    * 说明:测试端

    */

    public class Client {

    public static void main(String[] args) {

    Sword sabar = new Sword();

    sabar.setName("炽燃");

    sabar.setAtk(2000);

    System.out.println(QueryUtil.query(sabar));

    }

    }

    6.打印结果

    SELECT * FROM sword WHERE 1=1 and name='炽燃' and atk=2000

    用MySQL验证一下:

    213bc377bd292ef1c5ac8661758e3663.png

    终幕

    展开全文
  • 在controller接口方法接收参数加上@Valid注解 并且在实体类参数后紧跟 BindingResult bindingresulBindingResultMsgUtil工具类:public class BindingRequestMsgUtil {/*** 输出bindingResult中的错误信息* @param ...
  • 49 more 使用注解时总是出现这样的错误,但是配置文件没有错误,查阅之后是java版本导致的错误。 我创建项目时用的是1.8的,需要将其改成1.7的版本的就OK了。 我使用的spring是3.2.5的版本的。 这样就可以使用注解...
  • 全面解析Java注解1.为什么学习Java注解?学习Java注解有何好处?学完能做什么?(1)能·读懂别人写的代码,特别是框架相关的代码(2)让编程更加简洁,代码更加清晰(3)让别人高看一眼2.Java注解概念Java提供了一...
  • Java注解是附加在代码中的一些信息,用于一些工具在编译、运行时进行解析和使用,起到说明、配置的功能。注解不会也不能影响代码的实际逻辑,仅仅起到辅助性的作用。注解分为三类:1.内置注解;2.元注解;3.自定义...
  • eclipse编译项目:Java @Override 注解报错的解决方法
  • 对于Java注解,我之前的印象是很模糊的,总觉得这个东西经常听说,也经常用,但是具体是怎么回事,好像没有仔细学习过,说到注解,立马想到@Controller,仅此而已。对于Java注解,我咨询过一些身边的人,很多人表示...
  • 对于Java注解,我咨询过一些身边的人,很多人表示:知道怎么用,不熟悉不知道你是不是这样?在我没有系统性的学习一边注解的时候,我也是如此,在我花时间学习过注解之后,我觉得,对于注解,最重要的在于理解,很多...
  • 一、自定义一个注解(MyValidate),使用元注解定义各项用途二、定义该注解的业务逻辑,这里只实现了注解的一个属性:isNotNull()然后就就可以愉快的使用了实际项目中通过拦截器或者切面来实现:1、定义一个interf...
  • Java @Override 注解报错的解决方法

    千次阅读 2018-09-07 15:52:08
    java-&gt;Compiler–&gt;compiler compliance level 选择 1.6 或以上版本,刷新工程,重新编译。 另外也可以针对性的在项目上,鼠标右键选择 Properties–&gt;Java Compiler–&gt;compiler ...
  • 从JDK1.5开始,Java增加了对元数据的支持,也就是Annotation,首先说明注释和注解不是同一回事,是有区别的。本次分享的注解,其实就是代码里的特色标记而已,这些标记可以在代码的编译、类加载、运行时被读取,并且...
  • 如果你在 protected、private 或者 package-visible 的方法上使用 @Transactional 注解,它也不会报错, 但是这个被注解的方法将不会展示已配置的事务设置。 @Transactional 注解可以被应用于接口定义和接口方法、...
  • 注解的介绍: 在2005年,sun公司推出了jdk1.5,同时推出的注解功能吸引了很多人的目光,使用注解编写代码,能够减轻java程序员繁琐配置的痛苦。使用注解可以编写出更加易于维护,bug更少的代码。注解是什么呢?按照...
  • 最近在学Spring,在学习过程中遇到许多问题,其中遇到Java Spring aop注解报错Error creating bean with name ‘joggleimpleId’ defined in file [C:\Users\lenovo\Documents\workspace-sts-3.9.4.RELEASE\Spring-...
  • 使用Spring框架时,使用注解报错. ``` Caused by: org.springframework.core.NestedIOException: ASM ClassReader failed to parse class file - probably due to a new Java class file version that isn't ...
  • mybatis注解报错总结

    2019-10-27 14:16:08
    java.sql.SQLSyntaxErrorException:ORA-01745:invalid host/bind variable name 插入少量数据的时候是没有错的,插入大量数据时就会报错。(一下子插入了3万条数据,导致拼接的sql过长,所以报错) 解决方法:在...
  • 描述 问题1:在IDEA中右键没有创建class类的选项 解决方法:右键java目录,mark directory as...问题2:在执行了步骤1以后,发现启动类注解报错,无法引入包 解决方法:右键pom文件,run maven,选择reimport ...
  • lombok使用方式(1)idea中使用... (2)在Java项目的pom文件中添加依赖,使用注解就可以了。注解介绍(1) @Getter/@Setter注解可以针对类的属性字段自动生成Get/Set方法。public class Pojo{ @Setter @Getter priva...
  • 前言在 Java 应用程序中存在许多重复相似的、生成之后几乎不对其做更改的代码,但是我们还不得不花费很多精力编写它们来满足 Java 的编译需求比如,在 Java 应用程序开发中,我们几乎要为所有 Bean 的成员变量添加 ...
  • 源自:3-1 项目属性配置@Value("${name}") 这种注解报错是怎么回事org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'helloWorldSpringBoot': Injection of autowired ...
  • 注解方式下报java.lang.UnsupportedOperationException: Clobs are not cacheable 在hibernate Annotation中,实体BLOB、CLOB类型的注解与普通的实体属性有些不同,具体操作如下: BLOB类型,类型声明为byte[]:...
  • 关于sts@DATA注解报错解决方案

    千次阅读 2019-04-12 17:00:22
    拿过来的项目用sts导入进去 用到@Data注解的地方报错,找了很久解决方案如下: windows环境 1.下载lombok.jar包https://projectlombok.org/download.html 2.运行lombok.jar: java -jar D:\software\lombok.jar D:...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,520
精华内容 608
关键字:

java注解报错

java 订阅