zoukankan      html  css  js  c++  java
  • Spring技术与内幕(一)

    Spring生态网: https://spring.io/

    1. 简介

    可以把IOC和AOP理解为Spring的Kernel。通过IOC管理POJO对象以及它们之间的耦合关系;通过AOP以动态和非侵入式的方式来增强服务的功能。

    IOC:Inversion of Control 也称为依赖倒置原理(Dependency Inversion Principle):对象依赖关系的管理被反转了,对象之间的依赖关系由IoC容器进行管理,并且IoC完成对象的注入。

    (1)IoC包含了最为基本的IoC容器BeanFactory的接口与实现,比如XmlBeanFactory 就是一个最基本的BeanFactory(IoC容器)。BeanFactory是一个简单容器系列,只实现了容器基本的功能;另一

    个是ApplicationContext 上下文,它作为容器的高级形态存在,继承自BeanFactory并增加了许多面向框架的特性,同时对应用环境作了许多适配。在Spring提供的基本Ioc容器的接口定义和实现的

    基础上,Spring通过定义BeanDefinition来管理基于Spring的应用中的各种对象以及它们之间的相互依赖关系。BeanDefinition抽象了我们对Bean的定义,是让容器起作用的主要数据类型。

    BeanDefinition中维持了Bean是否是单例、是否Primary、是否Lazy等属性。

    BeanDefinition源码如下:

    package org.springframework.beans.factory.config;
    
    import org.springframework.beans.BeanMetadataElement;
    import org.springframework.beans.MutablePropertyValues;
    import org.springframework.core.AttributeAccessor;
    import org.springframework.lang.Nullable;
    
    public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {
    
        /**
         * Scope identifier for the standard singleton scope: "singleton".
         * <p>Note that extended bean factories might support further scopes.
         * @see #setScope
         */
        String SCOPE_SINGLETON = ConfigurableBeanFactory.SCOPE_SINGLETON;
    
        /**
         * Scope identifier for the standard prototype scope: "prototype".
         * <p>Note that extended bean factories might support further scopes.
         * @see #setScope
         */
        String SCOPE_PROTOTYPE = ConfigurableBeanFactory.SCOPE_PROTOTYPE;
    
    
        /**
         * Role hint indicating that a {@code BeanDefinition} is a major part
         * of the application. Typically corresponds to a user-defined bean.
         */
        int ROLE_APPLICATION = 0;
    
        /**
         * Role hint indicating that a {@code BeanDefinition} is a supporting
         * part of some larger configuration, typically an outer
         * {@link org.springframework.beans.factory.parsing.ComponentDefinition}.
         * {@code SUPPORT} beans are considered important enough to be aware
         * of when looking more closely at a particular
         * {@link org.springframework.beans.factory.parsing.ComponentDefinition},
         * but not when looking at the overall configuration of an application.
         */
        int ROLE_SUPPORT = 1;
    
        /**
         * Role hint indicating that a {@code BeanDefinition} is providing an
         * entirely background role and has no relevance to the end-user. This hint is
         * used when registering beans that are completely part of the internal workings
         * of a {@link org.springframework.beans.factory.parsing.ComponentDefinition}.
         */
        int ROLE_INFRASTRUCTURE = 2;
    
    
        // Modifiable attributes
    
        /**
         * Set the name of the parent definition of this bean definition, if any.
         */
        void setParentName(@Nullable String parentName);
    
        /**
         * Return the name of the parent definition of this bean definition, if any.
         */
        @Nullable
        String getParentName();
    
        /**
         * Specify the bean class name of this bean definition.
         * <p>The class name can be modified during bean factory post-processing,
         * typically replacing the original class name with a parsed variant of it.
         * @see #setParentName
         * @see #setFactoryBeanName
         * @see #setFactoryMethodName
         */
        void setBeanClassName(@Nullable String beanClassName);
    
        /**
         * Return the current bean class name of this bean definition.
         * <p>Note that this does not have to be the actual class name used at runtime, in
         * case of a child definition overriding/inheriting the class name from its parent.
         * Also, this may just be the class that a factory method is called on, or it may
         * even be empty in case of a factory bean reference that a method is called on.
         * Hence, do <i>not</i> consider this to be the definitive bean type at runtime but
         * rather only use it for parsing purposes at the individual bean definition level.
         * @see #getParentName()
         * @see #getFactoryBeanName()
         * @see #getFactoryMethodName()
         */
        @Nullable
        String getBeanClassName();
    
        /**
         * Override the target scope of this bean, specifying a new scope name.
         * @see #SCOPE_SINGLETON
         * @see #SCOPE_PROTOTYPE
         */
        void setScope(@Nullable String scope);
    
        /**
         * Return the name of the current target scope for this bean,
         * or {@code null} if not known yet.
         */
        @Nullable
        String getScope();
    
        /**
         * Set whether this bean should be lazily initialized.
         * <p>If {@code false}, the bean will get instantiated on startup by bean
         * factories that perform eager initialization of singletons.
         */
        void setLazyInit(boolean lazyInit);
    
        /**
         * Return whether this bean should be lazily initialized, i.e. not
         * eagerly instantiated on startup. Only applicable to a singleton bean.
         */
        boolean isLazyInit();
    
        /**
         * Set the names of the beans that this bean depends on being initialized.
         * The bean factory will guarantee that these beans get initialized first.
         */
        void setDependsOn(@Nullable String... dependsOn);
    
        /**
         * Return the bean names that this bean depends on.
         */
        @Nullable
        String[] getDependsOn();
    
        /**
         * Set whether this bean is a candidate for getting autowired into some other bean.
         * <p>Note that this flag is designed to only affect type-based autowiring.
         * It does not affect explicit references by name, which will get resolved even
         * if the specified bean is not marked as an autowire candidate. As a consequence,
         * autowiring by name will nevertheless inject a bean if the name matches.
         */
        void setAutowireCandidate(boolean autowireCandidate);
    
        /**
         * Return whether this bean is a candidate for getting autowired into some other bean.
         */
        boolean isAutowireCandidate();
    
        /**
         * Set whether this bean is a primary autowire candidate.
         * <p>If this value is {@code true} for exactly one bean among multiple
         * matching candidates, it will serve as a tie-breaker.
         */
        void setPrimary(boolean primary);
    
        /**
         * Return whether this bean is a primary autowire candidate.
         */
        boolean isPrimary();
    
        /**
         * Specify the factory bean to use, if any.
         * This the name of the bean to call the specified factory method on.
         * @see #setFactoryMethodName
         */
        void setFactoryBeanName(@Nullable String factoryBeanName);
    
        /**
         * Return the factory bean name, if any.
         */
        @Nullable
        String getFactoryBeanName();
    
        /**
         * Specify a factory method, if any. This method will be invoked with
         * constructor arguments, or with no arguments if none are specified.
         * The method will be invoked on the specified factory bean, if any,
         * or otherwise as a static method on the local bean class.
         * @see #setFactoryBeanName
         * @see #setBeanClassName
         */
        void setFactoryMethodName(@Nullable String factoryMethodName);
    
        /**
         * Return a factory method, if any.
         */
        @Nullable
        String getFactoryMethodName();
    
        /**
         * Return the constructor argument values for this bean.
         * <p>The returned instance can be modified during bean factory post-processing.
         * @return the ConstructorArgumentValues object (never {@code null})
         */
        ConstructorArgumentValues getConstructorArgumentValues();
    
        /**
         * Return if there are constructor argument values defined for this bean.
         * @since 5.0.2
         */
        default boolean hasConstructorArgumentValues() {
            return !getConstructorArgumentValues().isEmpty();
        }
    
        /**
         * Return the property values to be applied to a new instance of the bean.
         * <p>The returned instance can be modified during bean factory post-processing.
         * @return the MutablePropertyValues object (never {@code null})
         */
        MutablePropertyValues getPropertyValues();
    
        /**
         * Return if there are property values values defined for this bean.
         * @since 5.0.2
         */
        default boolean hasPropertyValues() {
            return !getPropertyValues().isEmpty();
        }
    
        /**
         * Set the name of the initializer method.
         * @since 5.1
         */
        void setInitMethodName(@Nullable String initMethodName);
    
        /**
         * Return the name of the initializer method.
         * @since 5.1
         */
        @Nullable
        String getInitMethodName();
    
        /**
         * Set the name of the destroy method.
         * @since 5.1
         */
        void setDestroyMethodName(@Nullable String destroyMethodName);
    
        /**
         * Return the name of the destroy method.
         * @since 5.1
         */
        @Nullable
        String getDestroyMethodName();
    
        /**
         * Set the role hint for this {@code BeanDefinition}. The role hint
         * provides the frameworks as well as tools with an indication of
         * the role and importance of a particular {@code BeanDefinition}.
         * @since 5.1
         * @see #ROLE_APPLICATION
         * @see #ROLE_SUPPORT
         * @see #ROLE_INFRASTRUCTURE
         */
        void setRole(int role);
    
        /**
         * Get the role hint for this {@code BeanDefinition}. The role hint
         * provides the frameworks as well as tools with an indication of
         * the role and importance of a particular {@code BeanDefinition}.
         * @see #ROLE_APPLICATION
         * @see #ROLE_SUPPORT
         * @see #ROLE_INFRASTRUCTURE
         */
        int getRole();
    
        /**
         * Set a human-readable description of this bean definition.
         * @since 5.1
         */
        void setDescription(@Nullable String description);
    
        /**
         * Return a human-readable description of this bean definition.
         */
        @Nullable
        String getDescription();
    
    
        // Read-only attributes
    
        /**
         * Return whether this a <b>Singleton</b>, with a single, shared instance
         * returned on all calls.
         * @see #SCOPE_SINGLETON
         */
        boolean isSingleton();
    
        /**
         * Return whether this a <b>Prototype</b>, with an independent instance
         * returned for each call.
         * @since 3.0
         * @see #SCOPE_PROTOTYPE
         */
        boolean isPrototype();
    
        /**
         * Return whether this bean is "abstract", that is, not meant to be instantiated.
         */
        boolean isAbstract();
    
        /**
         * Return a description of the resource that this bean definition
         * came from (for the purpose of showing context in case of errors).
         */
        @Nullable
        String getResourceDescription();
    
        /**
         * Return the originating BeanDefinition, or {@code null} if none.
         * Allows for retrieving the decorated bean definition, if any.
         * <p>Note that this method returns the immediate originator. Iterate through the
         * originator chain to find the original BeanDefinition as defined by the user.
         */
        @Nullable
        BeanDefinition getOriginatingBeanDefinition();
    
    }

    (2)在Spring具体的注入实现中,接口注入、setter注入、构造器注入是主要的注入方式。在Spring的IOC设计中,setter注入和构造器注入是主要的注入方式;相对而言,使用spring时setter注入是

    常见的注入方式,而且为了防止注入异常,spring IOC容器还提供了对特定依赖的检查。

    SpringAOP(Aspect-Oriented Programming): 围绕着AOP的增强功能,Spring集成了AsspectJ作为AOP的一个特定实现,同时还在JVM动态代理/Cglib代理的基础上实现了一个AOP框架。

    AOP是一种思想而不是一种技术。所以说,如果抛开spring,动态代理甚至静态代理都可以算是一种aop。spring中的aop实现分为两种,基于动态代理的aop和基于AspectJ的aop。AspectJ是完全

    独立于Spring存在的一个Eclipse发起的项目。AspectJ甚至可以说是一门独立的语言,在java文件编译期间,织入字节码,改变原有的类。

    我们常看到的在spring中用的@Aspect注解只不过是Spring2.0以后使用了AspectJ的风格而已,本质上还是Spring的原生实现。

    2.Spring源码构建

    Spring 源码是基于Gradle构建的,需要先安装Gradle。

    1.  安装Gradle

    2. 下载spring源码

    https://github.com/spring-projects/spring-framework/tree/5.1.x

    3. 到源码目录下执行

    点击Sping源码下 gradlew.bat 构建项目

    4.测试

    (1) build.gradle 如下

    plugins {
        id 'java'
    }
    
    group 'org.springframework'
    version '5.1.20.BUILD-SNAPSHOT'
    
    repositories {
        mavenCentral()
    }
    
    dependencies {
        compile(project(":spring-beans"))
        compile(project(":spring-core"))
        implementation(project(":spring-context"))
        testCompile group: 'junit', name: 'junit', version: '4.12'
    }

    (2) 测试Service

    package qz;
    
    import org.springframework.stereotype.Component;
    
    @Component
    public class UserService {
    
        public String method1() {
            System.out.println("method1");
            return "method1";
        }
    }

    (3) 测试主类

    package qz;
    
    import org.springframework.context.annotation.AnnotationConfigApplicationContext;
    import org.springframework.context.annotation.ComponentScan;
    import org.springframework.context.annotation.Configuration;
    
    /**
     * @author: 乔利强
     * @date: 2020/12/10 20:09
     * @description:
     */
    @ComponentScan("qz")
    @Configuration
    public class MainApp {
    
        public static void main(String[] args) {
            AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainApp.class);
            UserService bean = applicationContext.getBean(UserService.class);
            String s = bean.method1();
            System.out.println(s);
        }
    }

    (4) 结果如下:

    method1
    method1
    【当你用心写完每一篇博客之后,你会发现它比你用代码实现功能更有成就感!】
  • 相关阅读:
    普通文件的上传(表单上传和ajax文件异步上传)
    React Ant Design+Node.js Express+Mysql实现后端分页(带富文本编辑器)
    Express中增删改查相关的中间件
    React中使用富文本编辑器react-draft-wysiwyg
    Express中aixos请求的(批量)删除用POST方法,其它请求的(批量)删除可以用DELETE方法
    React中将字符串转义成html语句
    Vue中如何设置代理跨域请求数据
    React中如何设置代理跨域请求数据
    axios发送post请求,服务端无法正常获取参数(比如:node服务器无法通过req.body获取参数)解决方案
    LeetCode-162.寻找峰值
  • 原文地址:https://www.cnblogs.com/qlqwjy/p/14392196.html
Copyright © 2011-2022 走看看