android系统按键音framework流程源码详细解析

android 系统按键音framework源码解析(基于android 9.0)

今天来看下android中按键音的处理,首先看下按键是在那里开启的。然后再看看当按下按键后一个按键音是怎么播放出来的。

1.首先在setting app里面 SoundFragment.java

private void setSoundEffectsEnabled(boolean enabled) {
            mAudioManager = (AudioManager) getActivity().getSystemService(Context.AUDIO_SERVICE); //1
        if (enabled) {
            mAudioManager.loadSoundEffects();   // 从这里可以看到调用AudioManager里面的方法打开按键音
        } else {
            mAudioManager.unloadSoundEffects();
        }
        Settings.System.putInt(getActivity().getContentResolver(),
                Settings.System.SOUND_EFFECTS_ENABLED, enabled ? 1 : 0);
    }

大家可能很好奇像AudioManager,WifiManager等,都是通过getSystemService 这个方法得到的。这里花一点时间顺带先说一下1处这个吧。我们先一步一步来看。(其实最终还是回到AudioManager方法里面的,不感兴趣的可以直接跳过)。

2. framework/base/core/java/android/app/Activity.java

@Override
    public Object getSystemService(@ServiceName @NonNull String name) {
        if (getBaseContext() == null) {
            throw new IllegalStateException(
                    "System services not available to Activities before onCreate()");
        }
        if (WINDOW_SERVICE.equals(name)) {
            return mWindowManager;
        } else if (SEARCH_SERVICE.equals(name)) {
            ensureSearchManager();
            return mSearchManager;
        }
        return super.getSystemService(name);    //除了WINDOW_SERVICE和SEARCH_SERVICE外,其他服务都在父类中
    }

除了WINDOW_SERVICE和SEARCH_SERVICE外,其他服务都在父类中

3.framework/base/core/java/android/view/ContextThemeWrapper.java

@Override
    public Object getSystemService(String name) {
        if (LAYOUT_INFLATER_SERVICE.equals(name)) {
            if (mInflater == null) {
                mInflater = LayoutInflater.from(getBaseContext()).cloneInContext(this);
            }
            return mInflater;
            
        }
        return getBaseContext().getSystemService(name);  //还要再往上
    }

4. framework/base/core/java/android/content/Context.java

@SuppressWarnings("unchecked")
    public final @Nullable <T> T getSystemService(@NonNull Class<T> serviceClass) {
        // Because subclasses may override getSystemService(String) we cannot
        // perform a lookup by class alone.  We must first map the class to its
        // service name then invoke the string-based method.
        String serviceName = getSystemServiceName(serviceClass);
        return serviceName != null ? (T)getSystemService(serviceName) : null;
    }
/**
     * Gets the name of the system-level service that is represented by the specified class.
     *
     * @param serviceClass The class of the desired service.
     * @return The service name or null if the class is not a supported system service.
     */
    public abstract @Nullable String getSystemServiceName(@NonNull Class<?> serviceClass);

    /**
     * Use with {@link #getSystemService(String)} to retrieve a
     * {@link android.os.PowerManager} for controlling power management,
     * including "wake locks," which let you keep the device on while
     * you're running long tasks.
     */
    public static final String POWER_SERVICE = "power";

   /**
     * Use with {@link #getSystemService(String)} to retrieve a
     * {@link android.view.WindowManager} for accessing the system's window
     * manager.
     *
     * @see #getSystemService(String)
     * @see android.view.WindowManager
     */
    public static final String WINDOW_SERVICE = "window";

    /**
     * Use with {@link #getSystemService(String)} to retrieve a {@link
     * android.net.wifi.WifiManager} for handling management of
     * Wi-Fi access.
     *
     * @see #getSystemService(String)
     * @see android.net.wifi.WifiManager
     */
    public static final String WIFI_SERVICE = "wifi";

    /**
     * Use with {@link #getSystemService(String)} to retrieve a
     * {@link android.media.AudioManager} for handling management of volume,
     * ringer modes and audio routing.
     *
     * @see #getSystemService(String)
     * @see android.media.AudioManager    //在audiomanager 里面
     */
    public static final String AUDIO_SERVICE = "audio";
framework/base/media/java/android/media/AudioManager.java
**
 * AudioManager provides access to volume and ringer mode control.
 */
@SystemService(Context.AUDIO_SERVICE)  //通过注解来讲AUDIO_SERVICE与AudioManager绑定在一块
public class AudioManager {

    private Context mOriginalContext;
    private Context mApplicationContext;
    private long mVolumeKeyUpTime;

这里可以看到,之前那些wifimanager,audiomanager 都是这样来设置得到的。
好了,再继续说按键音的事,就是到AudioManager里面。

5. framework/base/media/java/android/media/AudioManager.java

/**
     *  Load Sound effects.
     *  This method must be called when sound effects are enabled.
*/
    public void loadSoundEffects() {
        final IAudioService service = getService();
        try {
            service.loadSoundEffects();
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }
private static IAudioService getService()
{
    if (sService != null) {
        return sService;
    }
    IBinder b = ServiceManager.getService(Context.AUDIO_SERVICE);
    sService = IAudioService.Stub.asInterface(b);
    return sService;
}

这里不得不再说一下。其实最后还是跑到AudiioService里面了。通过跨进程binder来拿到audioservice的对象。这里再顺带说一下那些service都是在哪里设置的。

6. framework/base/core/java/android/os/ServiceManager.java

/**
     * Returns a reference to a service with the given name
     * @param name the name of the service to get
     * @return a reference to the service, or <code>null</code> if the service doesn't exist
*/
    public static IBinder getService(String name) {
        try {
            IBinder service = sCache.get(name);   //在这个里面拿到
            if (service != null) {
                return service;
            } else {
                return Binder.allowBlocking(rawGetService(name));
            }
        } catch (RemoteException e) {
            Log.e(TAG, "error in getService", e);
        }
        return null;
    }
/**
     * Cache for the "well known" services, such as WM and AM.
*/
    private static HashMap<String, IBinder> sCache = new HashMap<String, IBinder>();

    /**
     * This is only intended to be called when the process is first being brought
     * up and bound by the activity manager. There is only one thread in the process
     * at that time, so no locking is done.
     *
     * @param cache the cache of service references
     * @hide
     */
    public static void initServiceCache(Map<String, IBinder> cache) {
        if (sCache.size() != 0) {
            throw new IllegalStateException("setServiceCache may only be called once");
        }
        sCache.putAll(cache);
    }

从上面可以看到 sCache 是一个Map。所以之前拿到的那些管理的对象(wifiManager,AudioManage,WindowManager等等),都是通过get map拿到的。

7. framework/base/services/core/java/com/android/server/audio/AudioService.java

/**
     * Loads samples into the soundpool.
     * This method must be called at first when sound effects are enabled
     */
    public boolean loadSoundEffects() {
        int attempts = 3;
        LoadSoundEffectReply reply = new LoadSoundEffectReply();

        synchronized (reply) {
            sendMsg(mAudioHandler, MSG_LOAD_SOUND_EFFECTS, SENDMSG_QUEUE, 0, 0, reply, 0); //发送消息
            while ((reply.mStatus == 1) && (attempts-- > 0)) {
                try {
                    reply.wait(SOUND_EFFECTS_LOAD_TIMEOUT_MS);
                } catch (InterruptedException e) {
                    Log.w(TAG, "loadSoundEffects Interrupted while waiting sound pool loaded.");
                }
            }
        }
        return (reply.mStatus == 0);
    }

当在setting里面打开按键音之后会调这来,从类名就可以看出是加载事件。后面按键声的的播放之前也会调用到这里来。

case MSG_LOAD_SOUND_EFFECTS:
                    //FIXME: onLoadSoundEffects() should be executed in a separate thread as it
                    // can take several dozens of milliseconds to complete
                    boolean loaded = onLoadSoundEffects();   // 调用这个方法
                    if (msg.obj != null) {
                        LoadSoundEffectReply reply = (LoadSoundEffectReply)msg.obj;
                        synchronized (reply) {
                            reply.mStatus = loaded ? 0 : -1;
                            reply.notify();
                        }
                    }
                    break;
private boolean onLoadSoundEffects() {
            int status;

            synchronized (mSoundEffectsLock) {
                if (!mSystemReady) {
                    Log.w(TAG, "onLoadSoundEffects() called before boot complete");
                    return false;
                }

                if (mSoundPool != null) {
                    return true;
                }

                loadTouchSoundAssets();     // 记载要播放声音的资源

                mSoundPool = new SoundPool.Builder()
                        .setMaxStreams(NUM_SOUNDPOOL_CHANNELS)
                        .setAudioAttributes(new AudioAttributes.Builder()
                            .setUsage(AudioAttributes.USAGE_ASSISTANCE_SONIFICATION)
                            .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
                            .build())
                        .build();    //链式调用
                mSoundPoolCallBack = null;
                mSoundPoolListenerThread = new SoundPoolListenerThread();
                mSoundPoolListenerThread.start();
                int attempts = 3;
                while ((mSoundPoolCallBack == null) && (attempts-- > 0)) {
                    try {
                        // Wait for mSoundPoolCallBack to be set by the other thread
                        mSoundEffectsLock.wait(SOUND_EFFECTS_LOAD_TIMEOUT_MS);
                    } catch (InterruptedException e) {
                        Log.w(TAG, "Interrupted while waiting sound pool listener thread.");
                    }
                }

                if (mSoundPoolCallBack == null) {
                    Log.w(TAG, "onLoadSoundEffects() SoundPool listener or thread creation error");
                    if (mSoundPoolLooper != null) {
                        mSoundPoolLooper.quit();
                        mSoundPoolLooper = null;
                    }
                    mSoundPoolListenerThread = null;
                    mSoundPool.release();
                    mSoundPool = null;
                    return false;
                }
                /*
                 * poolId table: The value -1 in this table indicates that corresponding
                 * file (same index in SOUND_EFFECT_FILES[] has not been loaded.
                 * Once loaded, the value in poolId is the sample ID and the same
                 * sample can be reused for another effect using the same file.
                 */
                int[] poolId = new int[SOUND_EFFECT_FILES.size()];
                for (int fileIdx = 0; fileIdx < SOUND_EFFECT_FILES.size(); fileIdx++) {
                    poolId[fileIdx] = -1;
                }
                /*
                 * Effects whose value in SOUND_EFFECT_FILES_MAP[effect][1] is -1 must be loaded.
                 * If load succeeds, value in SOUND_EFFECT_FILES_MAP[effect][1] is > 0:
                 * this indicates we have a valid sample loaded for this effect.
                 */

                int numSamples = 0;
                for (int effect = 0; effect < AudioManager.NUM_SOUND_EFFECTS; effect++) {
                    // Do not load sample if this effect uses the MediaPlayer
                    if (SOUND_EFFECT_FILES_MAP[effect][1] == 0) {
                        continue;
                    }
                    if (poolId[SOUND_EFFECT_FILES_MAP[effect][0]] == -1) {
                        String filePath = getSoundEffectFilePath(effect);
                        int sampleId = mSoundPool.load(filePath, 0);
                        if (sampleId <= 0) {
                            Log.w(TAG, "Soundpool could not load file: "+filePath);
                        } else {
                            SOUND_EFFECT_FILES_MAP[effect][1] = sampleId;
                            poolId[SOUND_EFFECT_FILES_MAP[effect][0]] = sampleId;
                            numSamples++;
                        }
                    } else {
                        SOUND_EFFECT_FILES_MAP[effect][1] =
                                poolId[SOUND_EFFECT_FILES_MAP[effect][0]];
                    }
                }
                // wait for all samples to be loaded
                if (numSamples > 0) {
                    mSoundPoolCallBack.setSamples(poolId);

                    attempts = 3;
                    status = 1;
                    while ((status == 1) && (attempts-- > 0)) {
                        try {
                            mSoundEffectsLock.wait(SOUND_EFFECTS_LOAD_TIMEOUT_MS);
                            status = mSoundPoolCallBack.status();
                        } catch (InterruptedException e) {
                            Log.w(TAG, "Interrupted while waiting sound pool callback.");
                        }
                    }
                } else {
                    status = -1;
                }

                if (mSoundPoolLooper != null) {
                    mSoundPoolLooper.quit();
                    mSoundPoolLooper = null;
                }
                mSoundPoolListenerThread = null;
                if (status != 0) {
                    Log.w(TAG,
                            "onLoadSoundEffects(), Error "+status+ " while loading samples");
                    for (int effect = 0; effect < AudioManager.NUM_SOUND_EFFECTS; effect++) {
                        if (SOUND_EFFECT_FILES_MAP[effect][1] > 0) {
                            SOUND_EFFECT_FILES_MAP[effect][1] = -1;
                        }
                    }

                    mSoundPool.release();
                    mSoundPool = null;
                }
            }
            return (status == 0);
        }

8.接下来看看当按下一个按键后按键音的触发

当按下一个按键或者焦点落到一个view上时,会有很多种情况,如下,

无论如何,最后都会调用到如下的方法中

framework/base/media/java/android/media/AudioManager.java

public void  playSoundEffect(int effectType) {
        if (effectType < 0 || effectType >= NUM_SOUND_EFFECTS) {
            return;
        }
        if (!querySoundEffectsEnabled(Process.myUserHandle().getIdentifier())) {
            return;
        }
        final IAudioService service = getService();
        try {
            service.playSoundEffect(effectType);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

还是会到AudioSetvice中。

9.framework/base/services/core/java/com/android/server/audio/AudioService.java

/** @see AudioManager#playSoundEffect(int) */
    public void playSoundEffect(int effectType) {
        playSoundEffectVolume(effectType, -1.0f);
    }

    /** @see AudioManager#playSoundEffect(int, float) */
    public void playSoundEffectVolume(int effectType, float volume) {
        // do not try to play the sound effect if the system stream is muted
        if (isStreamMutedByRingerOrZenMode(STREAM_SYSTEM)) {
            return;
        }

        if (effectType >= AudioManager.NUM_SOUND_EFFECTS || effectType < 0) {
            Log.w(TAG, "AudioService effectType value " + effectType + " out of range");
            return;
        }

        sendMsg(mAudioHandler, MSG_PLAY_SOUND_EFFECT, SENDMSG_QUEUE, // 发送消息
                effectType, (int) (volume * 1000), null, 0);
    }
case MSG_PLAY_SOUND_EFFECT:
                    onPlaySoundEffect(msg.arg1, msg.arg2);
                    break;

private void onPlaySoundEffect(int effectType, int volume) {
            synchronized (mSoundEffectsLock) {

                onLoadSoundEffects();    //上面提到过的的加载

                if (mSoundPool == null) {
                    return;
                }
                float volFloat;
                // use default if volume is not specified by caller
                if (volume < 0) {
                    volFloat = (float)Math.pow(10, (float)sSoundEffectVolumeDb/20);
                } else {
                    volFloat = volume / 1000.0f;
                }

                if (SOUND_EFFECT_FILES_MAP[effectType][1] > 0) {
                    mSoundPool.play(SOUND_EFFECT_FILES_MAP[effectType][1],
                                        volFloat, volFloat, 0, 0, 1.0f);
                } else {
                    MediaPlayer mediaPlayer = new MediaPlayer();
                    try {
                        String filePath = getSoundEffectFilePath(effectType);  //得到播放音频资源的地址。如果要替换资源,可以到此位置替换
                        mediaPlayer.setDataSource(filePath);
                        mediaPlayer.setAudioStreamType(AudioSystem.STREAM_SYSTEM);
                        mediaPlayer.prepare();
                        mediaPlayer.setVolume(volFloat);
                        mediaPlayer.setOnCompletionListener(new OnCompletionListener() {
                            public void onCompletion(MediaPlayer mp) {
                                cleanupPlayer(mp);
                            }
                        });
                        mediaPlayer.setOnErrorListener(new OnErrorListener() {
                            public boolean onError(MediaPlayer mp, int what, int extra) {
                                cleanupPlayer(mp);
                                return true;
                            }
                        });
                        mediaPlayer.start();     //开始播放
                    } catch (IOException ex) {
                        Log.w(TAG, "MediaPlayer IOException: "+ex);
                    } catch (IllegalArgumentException ex) {
                        Log.w(TAG, "MediaPlayer IllegalArgumentException: "+ex);
                    } catch (IllegalStateException ex) {
                        Log.w(TAG, "MediaPlayer IllegalStateException: "+ex);
                    }
                }
            }
        }

到此,android 系统的按键音的流程就走完了。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • android开发教程之framework增加字符串资源和图片等resource资源

    增加String 在Android frameworks/base/core/res/res/values中增加String,举例来说在string.xml增加一个String 复制代码 代码如下: <string name="serviceEnabledFor">Service was enabled for:</string> 也需要在 frameworks/base/core/res/res/values的public.xml文件中增加一个 复制代码 代码

  • Android中使用socket使底层和framework通信的实现方法

    一般的native和framework的通信是通过jni,但是这一般只是framework调用native,native如果有消息要怎样通知上层 呢?android中GSP模块提供一种解决思路,但是实现有些复杂,这里介绍一种使用socket通信的方法可以使native和framework自 由通信,具体实现如下: android中使用jni对linux中的socket进行了封装.使用起来十分的方便. 由于android是基于linux的,所以linux的代码会在java之前先执行,所以一般nat

  • Android Framework层获取及处理按键事件流程

    目录 前言 一.EventHub的getEvents() 二.InputReader的processEventsLocked() 前言 Android系统的输入事件是由InputManagerService服务来监控的,该系统服务在SystemServer的startOtherServices()中初始化.初始化的过程中会在Native层创建InputReaderThread和InputDispatcherThread两个线程,InputReaderThread的主要工作是读取输入事件,然后将输

  • Android O实现Framework层CENTER键长按功能方法

    目录 需求 原理 添加消息逻辑 添加按键处理 调用按键处理 需求 设备有一个按键,我们定义为了 KEYCODE_DPAD_CENTER(23),长按 5s,实现系统自动重启. 原理 在 Framework 层,查找长按电源键关机相关逻辑,可以看到按键经过一堆处理之后会来到 (/frameworks/base/services/core/java/com/android/server/policy/)PhoneWindowManager.java 定义的 interceptKeyBeforeQue

  • Ubuntu中为Android系统实现内置Java应用程序测试Application Frameworks层的硬件服务

    我们在Android系统增加硬件服务的目的是为了让应用层的APP能够通过Java接口来访问硬件服务.那么, APP如何通过Java接口来访问Application Frameworks层提供的硬件服务呢?在这一篇文章中,我们将在Android系统的应用层增加一个内置的应用程序,这个内置的应用程序通过ServiceManager接口获取指定的服务,然后通过这个服务来获得硬件服务.        一. 参照在Ubuntu Android实现Application Frameworks层增加硬件访问服

  • Ubuntu中为Android实现Application Frameworks层增加硬件访问服务

    在数字科技日新月异的今天,软件和硬件的完美结合,造就了智能移动设备的流行.今天大家对iOS和Android系统的趋之若鹜,一定程度上是由于这两个系统上有着丰富多彩的各种应用软件.因此,软件和硬件的关系,在一定程度上可以说,硬件是为软件服务的.硬件工程师研发出一款硬件设备,自然少了软件工程师为其编写驱动程序:而驱动程序的最终目的,是为了使得最上层的应用程序能够使用这些硬件提供的服务来为用户提供软件功能.对Android系统上的应用软件来说,就是要在系统的Application Frameworks

  • Android 往Framework中添加新资源的方法详解

    有时候我们想在标准的Framework中添加自己的新的资源怎么办呢?办法就是我们来尝试下.通过Eclipse的联系,我们可以联想到是否就是简单的把字符串放在res的各个文件夹里面.先来试试看,编译,系统立即报错.为什么呢?它提示你利用make update-api这个命令来更新public.xml文件或者把这个声明称hide类型.这个肯定不是我们想要的.所以方法有二:方法1:正常添加完资源后,执行make update-api函数.系统更新res/values/public.xml文件.方法2:

  • Android Framework Application Framework层简单介绍

    引言 Android的四层架构相比大家都很清楚,老生常谈的说一下分别为:Linux2.6内核层,核心库层,应用框架层,应用层.我今天重点介绍一下应用框架层Framework,其实也是我自己的学习心得. Framework层为我们开发应用程序提供了非常多的API,我们通过调用特殊的API构造我们的APP,满足我们业务上的需求.写APP的人都知道,学习Android开发的第一步就是去学习各种各样的API,什么Activity,Service,Notification等.这些都是framework提供

  • android系统按键音framework流程源码详细解析

    android 系统按键音framework源码解析(基于android 9.0) 今天来看下android中按键音的处理,首先看下按键是在那里开启的.然后再看看当按下按键后一个按键音是怎么播放出来的. 1.首先在setting app里面 SoundFragment.java private void setSoundEffectsEnabled(boolean enabled) {             mAudioManager = (AudioManager) getActivity(

  • 详解Android布局加载流程源码

    一.首先看布局层次 看这么几张图 我们会发现DecorView里面包裹的内容可能会随着不同的情况而变化,但是在Decor之前的层次关系都是固定的.即Activity包裹PhoneWindow,PhoneWindow包裹DecorView.接下来我们首先看一下三者分别是如何创建的. 二.Activity是如何创建的 首先看到入口类ActivityThread的performLaunchActivity方法: private Activity performLaunchActivity(Activi

  • RocketMQ之NameServer架构设计及启动关闭流程源码分析

    目录 NameServer 1.架构设计 2.核心类与配置 NamesrvController NamesrvConfig NettyServerConfig RouteInfoManager 3.启动与关闭流程 3.1.步骤一 3.2.步骤二 3.3.步骤三 NameServer 1.架构设计 消息中间件的设计思路一般都是基于主题订阅与发布的机制,RocketMQ也不例外.RocketMQ中,消息生产者(Producer)发送某主题的消息到消息服务器,消息服务器对消息进行持久化存储,而消息消费

  • RocketMQ消息发送流程源码剖析

    目录 正文 读源码 1 调用defaultMQProducerImpl.send() 2 设置过期时间 3 执行defaultMQProducerImpl.sendDefaultImpl()方法 sendDefaultImpl是发送消息的核心方法. 1 两个校验 2 获取topic路由信息 3 计算重试次数 4 执行队列选择方法 5 发送消息 正文 就是说,我们打了个比方,把RocketMQ比作码头上的一个小房子,来送孩子登船的家长比作生产者,拉走孩子们的船夫比作消费者,所以,RocketMQ的

  • 浅析Spring Security登录验证流程源码

    一.登录认证基于过滤器链 Spring Security的登录验证流程核心就是过滤器链.当一个请求到达时按照过滤器链的顺序依次进行处理,通过所有过滤器链的验证,就可以访问API接口了. SpringSecurity提供了多种登录认证的方式,由多种Filter过滤器来实现,比如: BasicAuthenticationFilter实现的是HttpBasic模式的登录认证 UsernamePasswordAuthenticationFilter实现用户名密码的登录认证 RememberMeAuthe

  • SpringSecurity 默认表单登录页展示流程源码

    SpringSecurity 默认表单登录页展示流程源码 本篇主要讲解 SpringSecurity提供的默认表单登录页 它是如何展示的的流程, 涉及 1.FilterSecurityInterceptor, 2.ExceptionTranslationFilc,xmccmc,ter , 3.DefaultLoginPageGeneratingFilter 过滤器, 并且简单介绍了 AccessDecisionManager 投票机制  1.准备工作(体验SpringSecurity默认表单认证

  • Spring Security 实现用户名密码登录流程源码详解

    目录 引言 探究 登录流程 校验 用户信息保存 引言 你在服务端的安全管理使用了 Spring Security,用户登录成功之后,Spring Security 帮你把用户信息保存在 Session 里,但是具体保存在哪里,要是不深究你可能就不知道, 这带来了一个问题,如果用户在前端操作修改了当前用户信息,在不重新登录的情况下,如何获取到最新的用户信息? 探究 无处不在的 Authentication 玩过 Spring Security 的小伙伴都知道,在 Spring Security 中

  • SpringMVC请求流程源码解析

    目录 一.SpringMVC使用 1.工程创建 2.工程配置 3.启动工程 二.SpringMVC启动过程 1.父容器启动过程 2.子容器启动过程(SpringMvc容器) 3.九大组件的初始化 1.处理器映射器的初始化 2.处理器适配器的初始化 4.拦截器的初始化 三.SpringMVC请求过程 1.请求流程图 2.业务描述 一.SpringMVC使用 1.工程创建 创建maven工程. 添加java.resources目录. 引入Spring-webmvc 依赖. <dependency>

  • Dubbo3的Spring适配原理与初始化流程源码解析

    目录 引言 Spring Context Initialization FactoryBean BeanDefinition 初始化bean 解决依赖 解决属性 Dubbo Spring的一些问题及解决办法 Dubbo spring 2.7 初始化过程 Dubbo spring 3的初始化过程 属性占位符解决失败 ReferenceBean被过早初始化问题 Reference注解可能出现@Autowire注入失败的问题 引言 Dubbo 国内影响力最大的开源框架之一,非常适合构建大规模微服务集群

  • Kubernetes kubectl中Pod创建流程源码解析

    目录 确立目标 先写一个Pod的Yaml 部署Pod 查询Pod kubectl create 的调用逻辑 Main Match Command Create RunCreate Summary 确立目标 从创建pod的全流程入手,了解各组件的工作内容,组件主要包括以下 kubectl kube-apiserver kube-scheduler kube-controller kubelet 理解各个组件之间的相互协作,目前是kubectl 先写一个Pod的Yaml apiVersion: v1

随机推荐