`

Java的注解机制——Spring自动装配的实现原理

 
阅读更多

jDK1.5加入了对注解机制的支持,实际上我学习Java的时候就已经使用JDK1.6了,而且除了@Override和@SuppressWarnings(后者还是IDE给生成的……)之外没接触过其他的。

 

  进入公司前的面试,技术人员就问了我关于注解的问题,我就说可以生成chm手册……现在想起来真囧,注释和注解被我搞得完全一样了。

 

  

 

  使用注解主要是在需要使用Spring框架的时候,特别是使用SpringMVC。因为这时我们会发现它的强大之处:预处理。

 

  注解实际上相当于一种标记,它允许你在运行时(源码、文档、类文件我们就不讨论了)动态地对拥有该标记的成员进行操作。

 

  实现注解需要三个条件(我们讨论的是类似于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放射机制。

 from:http://www.cnblogs.com/Johness/archive/2013/04/17/3026689.html

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 


 

分享到:
评论

相关推荐

    4Spring自动装配——annotation resource方式

    在Spring框架中,自动装配(Auto-Wiring)是一种简化依赖注入(Dependency Injection,DI)配置的方式,它允许...通过阅读和理解源码,我们可以更好地掌握Spring自动装配的工作原理,从而更好地利用这一强大的功能。

    java面试——Spring面试专题.zip

    在Java开发领域,Spring框架是不可或缺的重要组成部分,它极大地简化了企业级应用的开发工作。在面试中,Spring相关的知识往往是考察候选人技术能力的关键点。本面试专题将深入探讨Spring框架的核心概念、主要特性和...

    Spring依赖注入——java项目中使用spring注解方式进行注入.rar

    1. `@Autowired` 注解:这是Spring中最常用的注解,用于自动装配依赖。当Spring容器扫描到这个注解时,会自动寻找类型匹配的bean进行注入。如果存在多个候选bean,可以通过`@Qualifier`注解指定特定的bean。 2. `@...

    第五章 Spring4 自动装配、方法注入

    在本章中,我们将深入探讨Spring框架的核心特性之一——自动装配和方法注入。Spring作为一款广泛应用的Java企业级开发框架,极大地简化了依赖管理,提高了代码的可测试性和可维护性。自动装配和方法注入是Spring实现...

    Java模拟spring实现

    在真实Spring应用中,我们通常会使用`@Autowired`注解来自动装配依赖,但在这里我们手动配置。 最后,我们创建了一个简单的XML配置文件`beans.xml`,它定义了两个bean:`UserDAOImpl`和`UserService`。在`...

    使用 Spring 2.5 基于注解驱动的 Spring.pdf

    `@Autowired`注解用于自动装配Spring容器管理的Bean。在控制器类中,它可以被用来注入依赖的服务或组件,从而实现依赖注入(DI)。这不仅提高了代码的可读性和可维护性,还使得组件间的耦合度降低,更易于测试和扩展...

    详解如何在低版本的Spring中快速实现类似自动配置的功能

    综上所述,要在低版本的Spring中实现类似自动配置的功能,需要巧妙地利用Spring提供的扩展点,如BeanFactoryPostProcessor和BeanPostProcessor,以及Java Config和XML配置的组合。同时,还需要结合生命周期回调和...

    spring mvc + spring + hibernate 全注解整合开发视频教程 04

    在本视频教程“Spring MVC + Spring + Hibernate 全注解整合开发视频教程 04”中,我们将深入探讨Java企业级开发中的三大核心技术——Spring、Spring MVC和Hibernate的集成与应用,尤其是通过注解实现的简化配置。...

    使用 Spring 2.5 基于注解驱动的 Spring MVC

    3. **@Autowired**:用于自动装配Bean,可以省去在配置文件中显式定义Bean之间的依赖关系。 4. **@ModelAttribute**:用于将方法返回值或参数绑定到模型属性上,可以在方法签名前使用。 #### 示例分析 以下是一个...

    spring特点和原理.学习笔记

    本文将深入探讨Spring的核心特点——控制反转(IoC)和面向方面编程(AOP),以及它们在Spring框架中的实现原理。 **一、控制反转(IoC)** 控制反转(Inversion of Control,简称IoC)是Spring的核心概念之一,它...

    最简单的一个spring注解实例

    首先,我们需要了解Spring的核心组件——Spring容器,也称为ApplicationContext。这个容器负责管理应用程序中的bean,包括它们的创建、初始化、装配以及销毁。在没有注解的情况下,我们通常通过XML配置文件来定义...

    spring技术内幕-深入解析spring架构与设计原理

    《Spring技术内幕——深入解析Spring架构与设计原理》是一本深度剖析Spring框架核心机制与设计理念的专业书籍。本书旨在帮助读者全面理解Spring的内部工作原理,从而更好地应用和优化Spring框架在实际开发中的使用。...

    spring原理模拟

    Spring通过XML配置、注解或Java配置三种方式实现依赖注入。 接着,让我们来探讨Spring中的IoC(Inversion of Control)容器。IoC容器是Spring的核心,它负责管理应用中的所有对象。当容器启动时,会读取配置信息,...

    spring mvc + spring + hibernate 全注解整合开发视频教程 05

    在本视频教程“Spring MVC + Spring + Hibernate 全注解整合开发 05”中,我们将深入探讨Java企业级开发中的三大核心技术——Spring MVC、Spring和Hibernate的集成应用,特别是如何利用注解进行高效无XML配置的开发...

    Spring的IoC实现案例

    现在,我们将使用Spring的XML配置文件或Java配置类来声明和装配这些类。如果我们选择XML配置,可以这样编写: ```xml ``` 这将创建一个使用A4纸的`Priter`实例。如果我们想要切换到B5纸,只需要更改XML配置...

    Java Spring 源码解析 Xmind 思维导图

    源码解析会涵盖构造器注入、setter注入,以及自动装配的原理。 除此之外,Spring还包含了Web MVC、Data Access/Integration、Test等多个模块。例如,Web MVC提供了一种模型-视图-控制器的架构,使得构建Web应用变得...

    java毕业设计&课设-spring源码深度解析+注解开发全套视频教程(视频+源码).doc

    ### Java毕业设计&课设——Spring源码深度解析+注解开发全套视频教程知识点概览 #### 一、Spring框架简介 Spring框架是由Rod Johnson创建的一款开源轻量级Java EE应用框架,旨在简化企业级应用的开发过程。Spring...

    自主实现的简易Spring框架

    总的来说,这个项目为开发者提供了一个实践Spring核心概念的平台,通过实际编码加深对IoC和AOP的理解,对于提升Java开发技能和熟悉Spring框架的内部工作原理大有裨益。在实际使用过程中,可以逐步扩展和完善,例如...

    spring mvc + spring + hibernate 全注解整合开发视频教程 03

    在本视频教程“Spring MVC + Spring + Hibernate 全注解整合开发 03”中,我们将深入探讨Java企业级开发中的三大核心框架——Spring、Spring MVC和Hibernate的整合应用,尤其是利用注解进行的无XML配置。以下是这些...

    java或Java框架中常用的注解及其作用详解_资料.docx

    Java注解,也称为标注,是Java开发中的一个重要特性,自JDK 5.0引入。它们提供了一种元数据的方式,允许程序员在代码中添加信息...在实际项目中,结合Java注解和框架如Spring,可以实现松耦合和高度模块化的架构设计。

Global site tag (gtag.js) - Google Analytics