Java的注解机制——Spring自动装配的实现原理
来源:互联网 发布:java编写宿舍管理系统 编辑:程序博客网 时间:2024/06/15 12:42
注解实际上相当于一种标记,它允许你在运行时(源码、文档、类文件我们就不讨论了)动态地对拥有该标记的成员进行操作。
实现注解需要三个条件(我们讨论的是类似于Spring自动装配的高级应用):注解声明、使用注解的元素、操作使用注解元素的代码。
首先是注解声明,注解也是一种类型,我们要定义的话也需要编写代码,如下:
package annotation;import java.lang.annotation.ElementType;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;/** * 自定义注解,用来配置方法 * * @author Johness * */@Retention(RetentionPolicy.RUNTIME) // 表示注解在运行时依然存在@Target(ElementType.METHOD) // 表示注解可以被使用于方法上public @interface SayHiAnnotation { String paramValue() default "johness"; // 表示我的注解需要一个参数 名为"paramValue" 默认值为"johness"}然后是使用我们注解的元素:
package element;import annotation.SayHiAnnotation;/** * 要使用SayHiAnnotation的元素所在类 * 由于我们定义了只有方法才能使用我们的注解,我们就使用多个方法来进行测试 * * @author Johness * */public class SayHiEmlement { // 普通的方法 public void SayHiDefault(String name){ System.out.println("Hi, " + name); } // 使用注解并传入参数的方法 @SayHiAnnotation(paramValue="Jack") public void SayHiAnnotation(String name){ System.out.println("Hi, " + name); } // 使用注解并使用默认参数的方法 @SayHiAnnotation public void SayHiAnnotationDefault(String name){ System.out.println("Hi, " + name); }}最后,是我们的操作方法(值得一提的是虽然有一定的规范,但您大可不必去浪费精力,您只需要保证您的操作代码在您希望的时候执行即可):
package Main;import java.lang.reflect.InvocationTargetException;import java.lang.reflect.Method;import element.SayHiEmlement;import annotation.SayHiAnnotation;public class AnnotionOperator { public static void main(String[] args) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, ClassNotFoundException { SayHiEmlement element = new SayHiEmlement(); // 初始化一个实例,用于方法调用 Method[] methods = SayHiEmlement.class.getDeclaredMethods(); // 获得所有方法 for (Method method : methods) { SayHiAnnotation annotationTmp = null; if((annotationTmp = method.getAnnotation(SayHiAnnotation.class))!=null) // 检测是否使用了我们的注解 method.invoke(element,annotationTmp.paramValue()); // 如果使用了我们的注解,我们就把注解里的"paramValue"参数值作为方法参数来调用方法 else method.invoke(element, "Rose"); // 如果没有使用我们的注解,我们就需要使用普通的方式来调用方法了 } }}结果为:
Hi, Jack
Hi, johness
Hi, Rose
可以看到,注解是进行预处理的很好方式(这里的预处理和编译原理有区别)!
接下来我们看看Spring是如何使用注解机制完成自动装配的:
首先是为了让Spring为我们自动装配要进行的操作,无外乎两种:继承org.springframework.web.context.support.SpringBeanAutowiringSupport类或者添加@Component/@Controller等注解并(只是使用注解方式需要)在Spring配置文件里声明context:component-scan元素。我说说继承方式是如何实现自动装配的,我们打开Spring源代码查看SpringBeanAutowiringSupport类。我们会发现以下语句:
public SpringBeanAutowiringSupport() { processInjectionBasedOnCurrentContext(this);}众所周知,Java实例构造时会调用默认父类无参构造方法,Spring正是利用了这一点,让"操作元素的代码"得以执行!(我看到第一眼就震惊了!真是奇思妙想啊。果然,高手都要善于用Java来用Java)
后面的我就不就不多说了,不过还是要纠正一些人的观点:说使用注解的自动装配来完成注入也需要setter。这明显是错误的嘛!我们看Spring注解装配(继承方式)的方法调用顺序:
org.springframework.web.context.support.SpringBeanAutowiringSupport#SpringBeanAutowiringSupport=>
org.springframework.web.context.support.SpringBeanAutowiringSupport#processInjectionBasedOnCurrentContext=>
org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor#processInjection=>
org.springframework.beans.factory.annotation.InjectionMetadata#Injection(继承,方法重写)。
最后看看Injection方法的方法体:
/*** Either this or {@link #getResourceToInject} needs to be overridden.*/protected void inject(Object target, String requestingBeanName, PropertyValues pvs) throws Throwable {if (this.isField) {Field field = (Field) this.member;ReflectionUtils.makeAccessible(field);field.set(target, getResourceToInject(target, requestingBeanName));}else {if (checkPropertySkipping(pvs)) {return;}try {Method method = (Method) this.member;ReflectionUtils.makeAccessible(method);method.invoke(target, getResourceToInject(target, requestingBeanName));}catch (InvocationTargetException ex) {throw ex.getTargetException();}}}
- Java的注解机制——Spring自动装配的实现原理
- Java的注解机制——Spring自动装配的实现原理
- Java的注解机制——Spring自动装配的实现原理
- Java的注解机制——Spring自动装配的实现原理
- Java的注解机制——Spring自动装配的实现原理
- Java的注解机制——Spring自动装配的实现原理
- Java的注解机制——Spring自动装配的实现原理
- Java注解机制之Spring自动装配实现原理
- 使用spring注解 自动装配以及自动扫描机制 实现零xml配置的前提
- 使用spring注解 自动装配以及自动扫描机制 实现零xml配置的前提
- 使用spring注解 自动装配以及自动扫描机制 实现零xml配置的前提
- 使用spring注解 自动装配以及自动扫描机制 实现零xml配置的前提
- Spring Bean装配之基于Java的容器注解说明——基于泛型的自动装配
- Spring的自动装配机制
- Spring自动装配的注解用法
- spring 基于注解的自动装配
- Spring对bean的装配机制(一)——隐式自动装配
- Spring中bean的三种装配机制之——自动装配
- java编码格式
- svn 命令行下常用的几个命令
- mac 终端 常用命令
- 如何在Mac上使用Swift调用C接口开发条形码应用
- 总结系列-LayoutInflater的inflate函数用法详解
- Java的注解机制——Spring自动装配的实现原理
- Android 单元测试(四)测试 Activity和Fragment
- WPF 多线程---- 子线程操作界面主线程的元素
- Ubuntu 一条命令安装LAMP
- 野人学Android基础篇之初探UI控件第二课--ImageView动态赋值
- 网易新闻iOS版使用的开源组件
- javascript表单验证之SQL注入验证
- Parcelable传递图片,复杂对象,对象列表
- Tigase开发笔记1:深入认识XMPP协议