<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Asens</title>
    <description>The Plain is a minimalist Jekyll theme, that's it. Can't say anymore...</description>
    <link>https://asens.github.io</link>
    
      
        <item>
          <title>Spring interfaces</title>
          <description>&lt;h3 id=&quot;instantiationstrategy&quot;&gt;InstantiationStrategy?&lt;/h3&gt;

&lt;p&gt;负责创建RootBeanDefinition相应实例的接口&lt;/p&gt;

&lt;p&gt;实现类SimpleInstantiationStrategy&lt;/p&gt;

&lt;p&gt;实现了下列3个方法,factory是独立实现的&lt;/p&gt;

&lt;p&gt;如果beanDefination有MethodOverride的话需要有cglib子类初始化&lt;/p&gt;

&lt;pre class=&quot;java hljs&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt;?&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;interface&lt;/span&gt;?&lt;span class=&quot;hljs-title&quot;&gt;InstantiationStrategy&lt;/span&gt;?&lt;/span&gt;{
&lt;span class=&quot;hljs-comment&quot;&gt;//无参数的创建bean&lt;/span&gt;
????&lt;span class=&quot;hljs-function&quot;&gt;Object?&lt;span class=&quot;hljs-title&quot;&gt;instantiate&lt;/span&gt;&lt;span class=&quot;hljs-params&quot;&gt;(RootBeanDefinition?beanDefinition,?String?beanName,?BeanFactory?owner)&lt;/span&gt;
??????&lt;span class=&quot;hljs-keyword&quot;&gt;throws&lt;/span&gt;?BeansException&lt;/span&gt;;
??????&lt;span class=&quot;hljs-comment&quot;&gt;//有参数的创建bean&lt;/span&gt;
??????&lt;span class=&quot;hljs-function&quot;&gt;Object?&lt;span class=&quot;hljs-title&quot;&gt;instantiate&lt;/span&gt;&lt;span class=&quot;hljs-params&quot;&gt;(RootBeanDefinition?beanDefinition,?String?beanName,?BeanFactory?owner,
??????Constructor&lt;?&gt;?ctor,?Object[]?args)&lt;/span&gt;?&lt;span class=&quot;hljs-keyword&quot;&gt;throws&lt;/span&gt;?BeansException&lt;/span&gt;;
??????&lt;span class=&quot;hljs-comment&quot;&gt;//factoryBean的方式创建bean&lt;/span&gt;
??????&lt;span class=&quot;hljs-function&quot;&gt;Object?&lt;span class=&quot;hljs-title&quot;&gt;instantiate&lt;/span&gt;&lt;span class=&quot;hljs-params&quot;&gt;(RootBeanDefinition?beanDefinition,?String?beanName,?BeanFactory?owner,
??????Object?factoryBean,?Method?factoryMethod,?Object[]?args)&lt;/span&gt;?&lt;span class=&quot;hljs-keyword&quot;&gt;throws&lt;/span&gt;?BeansException&lt;/span&gt;;
}&lt;/pre&gt;

### BeanMetadataElement

搭载元数据配置来源的信息

&lt;pre class=&quot;java hljs&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt;?&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;interface&lt;/span&gt;?&lt;span class=&quot;hljs-title&quot;&gt;BeanMetadataElement&lt;/span&gt;?&lt;/span&gt;{

???&lt;span class=&quot;hljs-function&quot;&gt;Object?&lt;span class=&quot;hljs-title&quot;&gt;getSource&lt;/span&gt;&lt;span class=&quot;hljs-params&quot;&gt;()&lt;/span&gt;&lt;/span&gt;;

}&lt;/pre&gt;

### ParameterNameDiscoverer?

获取方法的参数的名字

实现类

&lt;span style=&quot;color: rgb(84, 141, 212);&quot;&gt;**PrioritizedParameterNameDiscoverer**&lt;/span&gt;:里面放一组parameterNameDiscoverers,取第一个

&lt;span style=&quot;color: rgb(84, 141, 212);&quot;&gt;**DefaultParameterNameDiscoverer**&lt;/span&gt;:判断是不是JDK1.8,JDK1.8有个refect.Parameter?

JDK1.8使用StandardReflectionParameterNameDiscoverer,使用Parameter极为简单

然而并不是,使用LocalVariableTableParameterNameDiscoverer需要读取字节码

&lt;pre class=&quot;hljs cs&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt;?&lt;span class=&quot;hljs-keyword&quot;&gt;interface&lt;/span&gt;?&lt;span class=&quot;hljs-title&quot;&gt;ParameterNameDiscoverer&lt;/span&gt;?{

???&lt;span class=&quot;hljs-comment&quot;&gt;/**
????*?Return?parameter?names?for?this?method
????*/&lt;/span&gt;
???&lt;span class=&quot;hljs-function&quot;&gt;String[]?&lt;span class=&quot;hljs-title&quot;&gt;getParameterNames&lt;/span&gt;(&lt;span class=&quot;hljs-params&quot;&gt;Method?method&lt;/span&gt;)&lt;/span&gt;;

???&lt;span class=&quot;hljs-comment&quot;&gt;/**
????*?Return?parameter?names?for?this?constructor,
????*/&lt;/span&gt;
???&lt;span class=&quot;hljs-function&quot;&gt;String[]?&lt;span class=&quot;hljs-title&quot;&gt;getParameterNames&lt;/span&gt;(&lt;span class=&quot;hljs-params&quot;&gt;Constructor&lt;?&gt;?ctor&lt;/span&gt;)&lt;/span&gt;;

}&lt;/pre&gt;

&lt;h3 id=&quot;autowirecandidateresolver&quot;&gt;AutowireCandidateResolver?&lt;/h3&gt;

&lt;p&gt;判断一个指定的beanDefination能无能成为一个指定bean的注入候选&lt;/p&gt;

&lt;p&gt;&lt;span style=&quot;color: rgb(84, 141, 212);&quot;&gt;&lt;strong&gt;SimpleAutowireCandidateResolver&lt;/strong&gt;&lt;/span&gt;:isAutowireCandidate直接返回beanDefination的属性,其他返回null&lt;/p&gt;

&lt;pre class=&quot;hljs java&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt;?&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;interface&lt;/span&gt;?&lt;span class=&quot;hljs-title&quot;&gt;AutowireCandidateResolver&lt;/span&gt;?&lt;/span&gt;{

????&lt;span class=&quot;hljs-comment&quot;&gt;//这个bean能不能注入的这个描述符的field里面&lt;/span&gt;
???&lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;boolean&lt;/span&gt;?&lt;span class=&quot;hljs-title&quot;&gt;isAutowireCandidate&lt;/span&gt;&lt;span class=&quot;hljs-params&quot;&gt;(BeanDefinitionHolder?bdHolder,?DependencyDescriptor?descriptor)&lt;/span&gt;&lt;/span&gt;;

???&lt;span class=&quot;hljs-function&quot;&gt;Object?&lt;span class=&quot;hljs-title&quot;&gt;getSuggestedValue&lt;/span&gt;&lt;span class=&quot;hljs-params&quot;&gt;(DependencyDescriptor?descriptor)&lt;/span&gt;&lt;/span&gt;;

???&lt;span class=&quot;hljs-function&quot;&gt;Object?&lt;span class=&quot;hljs-title&quot;&gt;getLazyResolutionProxyIfNecessary&lt;/span&gt;&lt;span class=&quot;hljs-params&quot;&gt;(DependencyDescriptor?descriptor,?String?beanName)&lt;/span&gt;&lt;/span&gt;;

}&lt;/pre&gt;

&lt;h3 id=&quot;beannamegenerator&quot;&gt;BeanNameGenerator?&lt;/h3&gt;

&lt;p&gt;生成bean的name&lt;/p&gt;

&lt;pre class=&quot;hljs cs&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt;?&lt;span class=&quot;hljs-keyword&quot;&gt;interface&lt;/span&gt;?&lt;span class=&quot;hljs-title&quot;&gt;BeanNameGenerator&lt;/span&gt;?{
????&lt;span class=&quot;hljs-function&quot;&gt;String?&lt;span class=&quot;hljs-title&quot;&gt;generateBeanName&lt;/span&gt;(&lt;span class=&quot;hljs-params&quot;&gt;BeanDefinition?definition,?BeanDefinitionRegistry?registry&lt;/span&gt;)&lt;/span&gt;;
}&lt;/pre&gt;

&lt;h3 id=&quot;beandefinitionreader&quot;&gt;BeanDefinitionReader?&lt;/h3&gt;

&lt;p&gt;读取BeanDefinition&lt;/p&gt;

&lt;p&gt;设计一个读取bean信息的东西需要什么&lt;/p&gt;

&lt;p&gt;读取完bean之后需要注册到beanDefination的map里面&lt;/p&gt;

&lt;p&gt;需要能加载资源的东西&lt;/p&gt;

&lt;p&gt;需要加载资源&lt;/p&gt;

&lt;p&gt;&lt;span style=&quot;color: rgb(84, 141, 212);&quot;&gt;&lt;strong&gt;AbstractBeanDefinitionReader&lt;/strong&gt;&lt;/span&gt;:实现了基本的接口除了loadBeanDefinitions(resource),基本都指向了这个函数&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;span style=&quot;color: rgb(84, 141, 212);&quot;&gt;XmlBeanDefinitionReader:&lt;/span&gt;&lt;/strong&gt;处理xml校验解析相关内容&lt;/p&gt;

&lt;pre class=&quot;hljs java&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt;?&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;interface&lt;/span&gt;?&lt;span class=&quot;hljs-title&quot;&gt;BeanDefinitionReader&lt;/span&gt;?&lt;/span&gt;{

???&lt;span class=&quot;hljs-function&quot;&gt;BeanDefinitionRegistry?&lt;span class=&quot;hljs-title&quot;&gt;getRegistry&lt;/span&gt;&lt;span class=&quot;hljs-params&quot;&gt;()&lt;/span&gt;&lt;/span&gt;;

???&lt;span class=&quot;hljs-function&quot;&gt;ResourceLoader?&lt;span class=&quot;hljs-title&quot;&gt;getResourceLoader&lt;/span&gt;&lt;span class=&quot;hljs-params&quot;&gt;()&lt;/span&gt;&lt;/span&gt;;

???&lt;span class=&quot;hljs-function&quot;&gt;ClassLoader?&lt;span class=&quot;hljs-title&quot;&gt;getBeanClassLoader&lt;/span&gt;&lt;span class=&quot;hljs-params&quot;&gt;()&lt;/span&gt;&lt;/span&gt;;
???&lt;span class=&quot;hljs-comment&quot;&gt;//名字生成器&lt;/span&gt;
???&lt;span class=&quot;hljs-function&quot;&gt;BeanNameGenerator?&lt;span class=&quot;hljs-title&quot;&gt;getBeanNameGenerator&lt;/span&gt;&lt;span class=&quot;hljs-params&quot;&gt;()&lt;/span&gt;&lt;/span&gt;;
????&lt;span class=&quot;hljs-comment&quot;&gt;//加载资源,返回数量&lt;/span&gt;
???&lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;int&lt;/span&gt;?&lt;span class=&quot;hljs-title&quot;&gt;loadBeanDefinitions&lt;/span&gt;&lt;span class=&quot;hljs-params&quot;&gt;(Resource?resource)&lt;/span&gt;?&lt;span class=&quot;hljs-keyword&quot;&gt;throws&lt;/span&gt;?BeanDefinitionStoreException&lt;/span&gt;;

???&lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;int&lt;/span&gt;?&lt;span class=&quot;hljs-title&quot;&gt;loadBeanDefinitions&lt;/span&gt;&lt;span class=&quot;hljs-params&quot;&gt;(Resource...?resources)&lt;/span&gt;?&lt;span class=&quot;hljs-keyword&quot;&gt;throws&lt;/span&gt;?BeanDefinitionStoreException&lt;/span&gt;;

???&lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;int&lt;/span&gt;?&lt;span class=&quot;hljs-title&quot;&gt;loadBeanDefinitions&lt;/span&gt;&lt;span class=&quot;hljs-params&quot;&gt;(String?location)&lt;/span&gt;?&lt;span class=&quot;hljs-keyword&quot;&gt;throws&lt;/span&gt;?BeanDefinitionStoreException&lt;/span&gt;;

???&lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;int&lt;/span&gt;?&lt;span class=&quot;hljs-title&quot;&gt;loadBeanDefinitions&lt;/span&gt;&lt;span class=&quot;hljs-params&quot;&gt;(String...?locations)&lt;/span&gt;?&lt;span class=&quot;hljs-keyword&quot;&gt;throws&lt;/span&gt;?BeanDefinitionStoreException&lt;/span&gt;;

}&lt;/pre&gt;

&lt;h3 id=&quot;resourceloader&quot;&gt;ResourceLoader?&lt;/h3&gt;

&lt;pre class=&quot;hljs cs&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt;?&lt;span class=&quot;hljs-keyword&quot;&gt;interface&lt;/span&gt;?&lt;span class=&quot;hljs-title&quot;&gt;ResourceLoader&lt;/span&gt;?{

???&lt;span class=&quot;hljs-comment&quot;&gt;//classpath:&lt;/span&gt;
???String?CLASSPATH_URL_PREFIX?=?ResourceUtils.CLASSPATH_URL_PREFIX;

????&lt;span class=&quot;hljs-comment&quot;&gt;/**
????*?根据位置加载资源
????*?&lt;li&gt;Must?support?fully?qualified?URLs,?e.g.?&quot;file:C:/test.dat&quot;.
????*?&lt;li&gt;Must?support?classpath?pseudo-URLs,?e.g.?&quot;classpath:test.dat&quot;.
????*?&lt;li&gt;Should?support?relative?file?paths,?e.g.?&quot;WEB-INF/test.dat&quot;.
????*/&amp;lt;/span&amp;gt;
???&lt;span class=&quot;hljs-function&quot;&gt;Resource?&lt;span class=&quot;hljs-title&quot;&gt;getResource&lt;/span&gt;(&lt;span class=&quot;hljs-params&quot;&gt;String?location&lt;/span&gt;)&lt;/span&gt;;

???&lt;span class=&quot;hljs-function&quot;&gt;ClassLoader?&lt;span class=&quot;hljs-title&quot;&gt;getClassLoader&lt;/span&gt;(&lt;span class=&quot;hljs-params&quot;&gt;&lt;/span&gt;)&lt;/span&gt;;

}&amp;lt;/pre&amp;gt;

### BeanDefinitionRegistry?

基本就是个map&amp;lt;String beanName,BeanDefination bd&amp;gt;

&lt;span style=&quot;color: rgb(84, 141, 212);&quot;&gt;**DefaultListableBeanFactory**&lt;/span&gt;

&lt;pre class=&quot;hljs java&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt;?&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;interface&lt;/span&gt;?&lt;span class=&quot;hljs-title&quot;&gt;BeanDefinitionRegistry&lt;/span&gt;?&lt;span class=&quot;hljs-keyword&quot;&gt;extends&lt;/span&gt;?&lt;span class=&quot;hljs-title&quot;&gt;AliasRegistry&lt;/span&gt;?&lt;/span&gt;{

???&lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;void&lt;/span&gt;?&lt;span class=&quot;hljs-title&quot;&gt;registerBeanDefinition&lt;/span&gt;&lt;span class=&quot;hljs-params&quot;&gt;(String?beanName,?BeanDefinition?beanDefinition)&lt;/span&gt;
?????????&lt;span class=&quot;hljs-keyword&quot;&gt;throws&lt;/span&gt;?BeanDefinitionStoreException&lt;/span&gt;;

???&lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;void&lt;/span&gt;?&lt;span class=&quot;hljs-title&quot;&gt;removeBeanDefinition&lt;/span&gt;&lt;span class=&quot;hljs-params&quot;&gt;(String?beanName)&lt;/span&gt;?&lt;span class=&quot;hljs-keyword&quot;&gt;throws&lt;/span&gt;?NoSuchBeanDefinitionException&lt;/span&gt;;

???&lt;span class=&quot;hljs-function&quot;&gt;BeanDefinition?&lt;span class=&quot;hljs-title&quot;&gt;getBeanDefinition&lt;/span&gt;&lt;span class=&quot;hljs-params&quot;&gt;(String?beanName)&lt;/span&gt;?&lt;span class=&quot;hljs-keyword&quot;&gt;throws&lt;/span&gt;?NoSuchBeanDefinitionException&lt;/span&gt;;

???&lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;boolean&lt;/span&gt;?&lt;span class=&quot;hljs-title&quot;&gt;containsBeanDefinition&lt;/span&gt;&lt;span class=&quot;hljs-params&quot;&gt;(String?beanName)&lt;/span&gt;&lt;/span&gt;;

???String[]?getBeanDefinitionNames();

???&lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;int&lt;/span&gt;?&lt;span class=&quot;hljs-title&quot;&gt;getBeanDefinitionCount&lt;/span&gt;&lt;span class=&quot;hljs-params&quot;&gt;()&lt;/span&gt;&lt;/span&gt;;

???&lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;boolean&lt;/span&gt;?&lt;span class=&quot;hljs-title&quot;&gt;isBeanNameInUse&lt;/span&gt;&lt;span class=&quot;hljs-params&quot;&gt;(String?beanName)&lt;/span&gt;&lt;/span&gt;;

}&lt;/pre&gt;

### PropertyResolver?

解决各种source属性的接口

&lt;pre class=&quot;hljs java&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt;?&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;interface&lt;/span&gt;?&lt;span class=&quot;hljs-title&quot;&gt;PropertyResolver&lt;/span&gt;?&lt;/span&gt;{

???&lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;boolean&lt;/span&gt;?&lt;span class=&quot;hljs-title&quot;&gt;containsProperty&lt;/span&gt;&lt;span class=&quot;hljs-params&quot;&gt;(String?key)&lt;/span&gt;&lt;/span&gt;;

???&lt;span class=&quot;hljs-function&quot;&gt;String?&lt;span class=&quot;hljs-title&quot;&gt;getProperty&lt;/span&gt;&lt;span class=&quot;hljs-params&quot;&gt;(String?key)&lt;/span&gt;&lt;/span&gt;;

???&lt;span class=&quot;hljs-function&quot;&gt;String?&lt;span class=&quot;hljs-title&quot;&gt;getProperty&lt;/span&gt;&lt;span class=&quot;hljs-params&quot;&gt;(String?key,?String?defaultValue)&lt;/span&gt;&lt;/span&gt;;

???&lt;T&gt;?&lt;span class=&quot;hljs-function&quot;&gt;T?&lt;span class=&quot;hljs-title&quot;&gt;getProperty&lt;/span&gt;&lt;span class=&quot;hljs-params&quot;&gt;(String?key,?Class&lt;T&gt;?targetType)&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;;

???&lt;T&gt;?&lt;span class=&quot;hljs-function&quot;&gt;T?&lt;span class=&quot;hljs-title&quot;&gt;getProperty&lt;/span&gt;&lt;span class=&quot;hljs-params&quot;&gt;(String?key,?Class&lt;T&gt;?targetType,?T?defaultValue)&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;;

???&lt;T&gt;?&lt;span class=&quot;hljs-function&quot;&gt;Class&lt;T&gt;?&lt;span class=&quot;hljs-title&quot;&gt;getPropertyAsClass&lt;/span&gt;&lt;span class=&quot;hljs-params&quot;&gt;(String?key,?Class&lt;T&gt;?targetType)&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;;

???&lt;span class=&quot;hljs-function&quot;&gt;String?&lt;span class=&quot;hljs-title&quot;&gt;getRequiredProperty&lt;/span&gt;&lt;span class=&quot;hljs-params&quot;&gt;(String?key)&lt;/span&gt;?&lt;span class=&quot;hljs-keyword&quot;&gt;throws&lt;/span&gt;?IllegalStateException&lt;/span&gt;;

???&lt;T&gt;?&lt;span class=&quot;hljs-function&quot;&gt;T?&lt;span class=&quot;hljs-title&quot;&gt;getRequiredProperty&lt;/span&gt;&lt;span class=&quot;hljs-params&quot;&gt;(String?key,?Class&lt;T&gt;?targetType)&amp;lt;/span&amp;gt;?&lt;span class=&quot;hljs-keyword&quot;&gt;throws&lt;/span&gt;?IllegalStateException&amp;lt;/span&amp;gt;;

???&lt;span class=&quot;hljs-function&quot;&gt;String?&lt;span class=&quot;hljs-title&quot;&gt;resolvePlaceholders&lt;/span&gt;&lt;span class=&quot;hljs-params&quot;&gt;(String?text)&lt;/span&gt;&lt;/span&gt;;

???&lt;span class=&quot;hljs-function&quot;&gt;String?&lt;span class=&quot;hljs-title&quot;&gt;resolveRequiredPlaceholders&lt;/span&gt;&lt;span class=&quot;hljs-params&quot;&gt;(String?text)&lt;/span&gt;?&lt;span class=&quot;hljs-keyword&quot;&gt;throws&lt;/span&gt;?IllegalArgumentException&lt;/span&gt;;

}&amp;lt;/pre&amp;gt;

Environment?

表示当前应用程序正在运行的环境的接口

配置文件和属性

无论是在XML中还是通过注释定义的配置文件

可能源自各种来源：属性文件，JVM系统属性，系统,环境变量，JNDI，servlet上下文参数，ad-hoc属性对象，地图等等。

环境对象与属性关系的作用是为用户提供方便的服务接口，用于配置资源并从中解析属性。

&lt;pre class=&quot;hljs java&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt;?&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;interface&lt;/span&gt;?&lt;span class=&quot;hljs-title&quot;&gt;Environment&lt;/span&gt;?&lt;span class=&quot;hljs-keyword&quot;&gt;extends&lt;/span&gt;?&lt;span class=&quot;hljs-title&quot;&gt;PropertyResolver&lt;/span&gt;?&lt;/span&gt;{

???String[]?getActiveProfiles();

???String[]?getDefaultProfiles();

???&lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;boolean&lt;/span&gt;?&lt;span class=&quot;hljs-title&quot;&gt;acceptsProfiles&lt;/span&gt;&lt;span class=&quot;hljs-params&quot;&gt;(String...?profiles)&lt;/span&gt;&lt;/span&gt;;

}&lt;/pre&gt;

### BeanDefinitionDocumentReader?

注册bean

&lt;span style=&quot;color: rgb(84, 141, 212);&quot;&gt;**DefaultBeanDefinitionDocumentReade**&lt;/span&gt;&lt;span style=&quot;color: rgb(84, 141, 212);&quot;&gt;**r**&lt;/span&gt;:整个类都在处理这个接口registerBeanDefinitions

&lt;pre class=&quot;hljs java&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt;?&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;interface&lt;/span&gt;?&lt;span class=&quot;hljs-title&quot;&gt;BeanDefinitionDocumentReader&lt;/span&gt;?&lt;/span&gt;{

???&lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;void&lt;/span&gt;?&lt;span class=&quot;hljs-title&quot;&gt;setEnvironment&lt;/span&gt;&lt;span class=&quot;hljs-params&quot;&gt;(Environment?environment)&lt;/span&gt;&lt;/span&gt;;

???&lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;void&lt;/span&gt;?&lt;span class=&quot;hljs-title&quot;&gt;registerBeanDefinitions&lt;/span&gt;&lt;span class=&quot;hljs-params&quot;&gt;(Document?doc,?XmlReaderContext?readerContext)&lt;/span&gt;
?????????&lt;span class=&quot;hljs-keyword&quot;&gt;throws&lt;/span&gt;?BeanDefinitionStoreException&lt;/span&gt;;

}&lt;/pre&gt;
&lt;/T&gt;&lt;/span&gt;&lt;/span&gt;&lt;/T&gt;&lt;/T&gt;&lt;/span&gt;&lt;/T&gt;&lt;/span&gt;&lt;/T&gt;&lt;/T&gt;&lt;/span&gt;&lt;/span&gt;&lt;/T&gt;&lt;/T&gt;&lt;/span&gt;&lt;/span&gt;&lt;/T&gt;&lt;/pre&gt;&lt;/li&gt;&lt;/li&gt;&lt;/li&gt;&lt;/span&gt;&lt;/pre&gt;
</description>
          <pubDate>2017-07-03T00:00:00+08:00</pubDate>
          <link>https://asens.github.io/notes/Spring-Interfaces</link>
          <guid isPermaLink="true">https://asens.github.io/notes/Spring-Interfaces</guid>
        </item>
      
    
      
        <item>
          <title>Redis安装和使用</title>
          <description>&lt;p&gt;&lt;strong&gt;下载地址：&lt;/strong&gt;&lt;a href=&quot;https://github.com/MSOpenTech/redis/releases&quot;&gt;https://github.com/MSOpenTech/redis/releases&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;打开一个 &lt;strong&gt;cmd&lt;/strong&gt; 窗口 使用cd命令切换目录到 &lt;strong&gt;C:
edis&lt;/strong&gt; 运行 &lt;strong&gt;redis-server.exe redis.windows.conf&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;**
**&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;img src=&quot;https://img.asens.cn/images/note/1/as149725956733044.jpg&quot; alt=&quot;&quot; /&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;**
**&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;img src=&quot;https://img.asens.cn/images/note/1/as149725959142444.jpg&quot; alt=&quot;&quot; /&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;**
**&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Java&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;**
**&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;pom&lt;/strong&gt;&lt;/p&gt;
&lt;pre class=&quot;xml&quot;&gt;&amp;lt;!--spring-data-redis&amp;nbsp;高版本会有问题--&amp;gt;
&amp;lt;dependency&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;lt;groupId&amp;gt;org.springframework.data&amp;lt;/groupId&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;lt;artifactId&amp;gt;spring-data-redis&amp;lt;/artifactId&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;lt;version&amp;gt;1.6.2.RELEASE&amp;lt;/version&amp;gt;
&amp;lt;/dependency&amp;gt;

&amp;lt;dependency&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;lt;groupId&amp;gt;org.apache.commons&amp;lt;/groupId&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;lt;artifactId&amp;gt;commons-pool2&amp;lt;/artifactId&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;lt;version&amp;gt;2.1&amp;lt;/version&amp;gt;
&amp;lt;/dependency&amp;gt;

&amp;lt;dependency&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;lt;groupId&amp;gt;redis.clients&amp;lt;/groupId&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;lt;artifactId&amp;gt;jedis&amp;lt;/artifactId&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;lt;version&amp;gt;2.9.0&amp;lt;/version&amp;gt;
&amp;lt;/dependency&amp;gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;spring bean 连接信息&lt;/strong&gt;&lt;/p&gt;

&lt;pre class=&quot;xml&quot;&gt;&amp;lt;bean&amp;nbsp;id=&amp;quot;jedisConnFactory&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;class=&amp;quot;org.springframework.data.redis.connection.jedis.JedisConnectionFactory&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;p:use-pool=&amp;quot;true&amp;quot;&amp;nbsp;p:host-name=&amp;quot;127.0.0.1&amp;quot;&amp;nbsp;p:port=&amp;quot;6379&amp;quot;/&amp;gt;

&amp;lt;bean&amp;nbsp;id=&amp;quot;redisTemplate&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;class=&amp;quot;org.springframework.data.redis.core.RedisTemplate&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;p:connection-factory-ref=&amp;quot;jedisConnFactory&amp;quot;/&amp;gt;&lt;/pre&gt;

&lt;p&gt;JRedis的使用&lt;/p&gt;

&lt;pre class=&quot;java&quot;&gt;public&amp;nbsp;static&amp;nbsp;void&amp;nbsp;main(String[]&amp;nbsp;aa){
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Jedis&amp;nbsp;jedis&amp;nbsp;=&amp;nbsp;new&amp;nbsp;Jedis(&amp;quot;localhost&amp;quot;);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;System.out.println(&amp;quot;Connection&amp;nbsp;to&amp;nbsp;server&amp;nbsp;sucessfully&amp;quot;);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//存储数据到列表中
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;jedis.lpush(&amp;quot;tutorial-list&amp;quot;,&amp;nbsp;&amp;quot;Redis&amp;quot;);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;jedis.lpush(&amp;quot;tutorial-list&amp;quot;,&amp;nbsp;&amp;quot;Mongodb&amp;quot;);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;jedis.lpush(&amp;quot;tutorial-list&amp;quot;,&amp;nbsp;&amp;quot;Mysql&amp;quot;);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp;获取存储的数据并输出
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;List&amp;lt;String&amp;gt;&amp;nbsp;list&amp;nbsp;=&amp;nbsp;jedis.lrange(&amp;quot;tutorial-list&amp;quot;,&amp;nbsp;0&amp;nbsp;,5);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;for(int&amp;nbsp;i=0;&amp;nbsp;i&amp;lt;list.size();&amp;nbsp;i++)&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;System.out.println(&amp;quot;Stored&amp;nbsp;string&amp;nbsp;in&amp;nbsp;redis::&amp;nbsp;&amp;quot;+list.get(i));
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
}&lt;/pre&gt;

&lt;p&gt;Spring的使用&lt;/p&gt;

&lt;pre class=&quot;java&quot;&gt;@Controller
public&amp;nbsp;class&amp;nbsp;Example&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;@Autowired
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;private&amp;nbsp;RedisTemplate&amp;lt;String,&amp;nbsp;String&amp;gt;&amp;nbsp;template;

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;@RequestMapping(&amp;quot;/testRedis&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public&amp;nbsp;void&amp;nbsp;testRedis()&amp;nbsp;throws&amp;nbsp;MalformedURLException&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;addLink(&amp;quot;1&amp;quot;,&amp;quot;http://www.asens.cn&amp;quot;);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;String&amp;nbsp;url=getFormLink(&amp;quot;1&amp;quot;);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;System.out.println(url);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public&amp;nbsp;void&amp;nbsp;addLink(String&amp;nbsp;userId,&amp;nbsp;String&amp;nbsp;url)&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;template.boundListOps(userId).leftPush(url);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public&amp;nbsp;String&amp;nbsp;getFormLink(String&amp;nbsp;userId)&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;template.boundListOps(userId).leftPop();
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
}&lt;/pre&gt;
</description>
          <pubDate>2017-07-03T00:00:00+08:00</pubDate>
          <link>https://asens.github.io/notes/Redis%E5%AE%89%E8%A3%85%E5%92%8C%E4%BD%BF%E7%94%A8</link>
          <guid isPermaLink="true">https://asens.github.io/notes/Redis%E5%AE%89%E8%A3%85%E5%92%8C%E4%BD%BF%E7%94%A8</guid>
        </item>
      
    
      
        <item>
          <title>Netty启动流程(4)</title>
          <description>&lt;pre class=&quot;java&quot;&gt;public&amp;nbsp;Channel&amp;nbsp;bind(final&amp;nbsp;SocketAddress&amp;nbsp;localAddress)&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ChannelFuture&amp;nbsp;future&amp;nbsp;=&amp;nbsp;bindAsync(localAddress);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;future.awaitUninterruptibly();
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;future.getChannel();
}&lt;/pre&gt;

&lt;p&gt;从bindAsync开始说起吧,异步的绑定端口&lt;/p&gt;

&lt;p&gt;awaitUninterruptibly如果没有done会wait()直到被人叫醒,这个操作是属于future的&lt;/p&gt;

&lt;p&gt;在bindAsync中&lt;/p&gt;

&lt;pre class=&quot;java&quot;&gt;Binder&amp;nbsp;binder&amp;nbsp;=&amp;nbsp;new&amp;nbsp;Binder(localAddress);
ChannelPipeline&amp;nbsp;bossPipeline&amp;nbsp;=&amp;nbsp;pipeline();
bossPipeline.addLast(&amp;quot;binder&amp;quot;,&amp;nbsp;binder);
Channel&amp;nbsp;channel&amp;nbsp;=&amp;nbsp;getFactory().newChannel(bossPipeline);
final&amp;nbsp;ChannelFuture&amp;nbsp;bfuture&amp;nbsp;=&amp;nbsp;new&amp;nbsp;DefaultChannelFuture(channel,&amp;nbsp;false);
System.out.println(Thread.currentThread().getName()+&amp;quot;&amp;nbsp;:&amp;nbsp;bindFuture&amp;nbsp;addListener&amp;quot;);
binder.bindFuture.addListener(new&amp;nbsp;ChannelFutureListener()&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public&amp;nbsp;void&amp;nbsp;operationComplete(ChannelFuture&amp;nbsp;future)&amp;nbsp;throws&amp;nbsp;Exception&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;(future.isSuccess())&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;System.out.println(Thread.currentThread().getName()+&amp;quot;&amp;nbsp;:&amp;nbsp;bfuture&amp;nbsp;操作完成&amp;nbsp;回调setSuccess&amp;quot;);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;bfuture.setSuccess();
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&amp;nbsp;else&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp;Call&amp;nbsp;close&amp;nbsp;on&amp;nbsp;bind&amp;nbsp;failure
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;bfuture.getChannel().close();
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;bfuture.setFailure(future.getCause());
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
});
return&amp;nbsp;bfuture;&lt;/pre&gt;

&lt;p&gt;初始化一个binder ,继承SimpleChannelUpstreamHandler,负责绑定端口&lt;/p&gt;

&lt;p&gt;初始化一个boss的pipeline,将这个handler放入pipeline里面&lt;/p&gt;

&lt;p&gt;初始化一个channel&lt;/p&gt;

&lt;p&gt;this是factory&lt;/p&gt;

&lt;p&gt;我要初始化一个channel,我要设置对应的属性,打开ServerSocketChannel,设置为非阻塞,感兴趣的事件设置为read&lt;/p&gt;

&lt;p&gt;然后创建一个config,然后通知channel open的事件&lt;/p&gt;
&lt;pre class=&quot;brush:java;toolbar:false;&quot;&gt;return&amp;nbsp;new&amp;nbsp;NioServerSocketChannel(this,&amp;nbsp;pipeline,&amp;nbsp;sink,&amp;nbsp;bossPool.nextBoss(),&amp;nbsp;workerPool);

static&amp;nbsp;final&amp;nbsp;ConcurrentMap&amp;lt;Integer,&amp;nbsp;Channel&amp;gt;&amp;nbsp;allChannels&amp;nbsp;=&amp;nbsp;new&amp;nbsp;ConcurrentHashMap&amp;lt;Integer,&amp;nbsp;Channel&amp;gt;();

int&amp;nbsp;interestOps&amp;nbsp;=&amp;nbsp;OP_READ;

NioServerSocketChannel(
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ChannelFactory&amp;nbsp;factory,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ChannelPipeline&amp;nbsp;pipeline,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ChannelSink&amp;nbsp;sink,&amp;nbsp;Boss&amp;nbsp;boss,&amp;nbsp;WorkerPool&amp;lt;NioWorker&amp;gt;&amp;nbsp;workerPool)&amp;nbsp;{

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//set各种属性
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//random一个id

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;socket&amp;nbsp;=&amp;nbsp;ServerSocketChannel.open();
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;socket.configureBlocking(false);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;config&amp;nbsp;=&amp;nbsp;new&amp;nbsp;DefaultServerSocketChannelConfig(socket.socket());
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;fireChannelOpen(this);
}&lt;/pre&gt;

&lt;p&gt;在fireChannelOpen中sendUpstream,里面Event的channel就是刚才的newChannel,也就是NioServerSocketChannel&lt;/p&gt;

&lt;pre class=&quot;brush:java;toolbar:false;&quot;&gt;channel.getPipeline().sendUpstream(
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;new&amp;nbsp;UpstreamChannelStateEvent(
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;channel,&amp;nbsp;ChannelState.OPEN,&amp;nbsp;Boolean.TRUE));&lt;/pre&gt;

&lt;pre class=&quot;brush:java;toolbar:false;&quot;&gt;//找到一个可以获取能够处理Upstream的handler,也就是刚才的binder
public&amp;nbsp;void&amp;nbsp;sendUpstream(ChannelEvent&amp;nbsp;e)&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;DefaultChannelHandlerContext&amp;nbsp;head&amp;nbsp;=&amp;nbsp;getActualUpstreamContext(this.head);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;sendUpstream(head,&amp;nbsp;e);
}

((ChannelUpstreamHandler)&amp;nbsp;ctx.getHandler()).handleUpstream(ctx,&amp;nbsp;e);&lt;/pre&gt;

&lt;p&gt;binder并没有重载handleUpstream,因此执行他的父类的SimpleChannelUpstreamHandler的handleUpstream&lt;/p&gt;

&lt;pre class=&quot;brush:java;toolbar:false;&quot;&gt;if&amp;nbsp;(e&amp;nbsp;instanceof&amp;nbsp;ChannelStateEvent)&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;switch&amp;nbsp;(evt.getState())&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;case&amp;nbsp;OPEN:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;(Boolean.TRUE.equals(evt.getValue()))&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;channelOpen(ctx,&amp;nbsp;evt);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
}&lt;/pre&gt;

&lt;p&gt;binder重载了channelOpen的方法&lt;/p&gt;

&lt;pre class=&quot;brush:java;toolbar:false;&quot;&gt;evt.getChannel().bind(localAddress).addListener(new&amp;nbsp;ChannelFutureListener()&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public&amp;nbsp;void&amp;nbsp;operationComplete(ChannelFuture&amp;nbsp;future)&amp;nbsp;throws&amp;nbsp;Exception&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;(future.isSuccess())&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;bindFuture.setSuccess();
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&amp;nbsp;else&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;bindFuture.setFailure(future.getCause());
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
});&lt;/pre&gt;

&lt;p&gt;调用的是刚才的NioServerSocketChannel的bind方法,在父类AbstractChannel里面&lt;/p&gt;

&lt;p&gt;new一个ChannelFuture,这个future是在binder中调用的那个bind产生的future,会在这个sedDownstream结束后返回到binder里面并addListener,这个要看一下究竟是谁调用的这个future的operationComplete&lt;/p&gt;
&lt;pre class=&quot;brush:java;toolbar:false;&quot;&gt;public&amp;nbsp;ChannelFuture&amp;nbsp;bind(SocketAddress&amp;nbsp;localAddress)&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;Channels.bind(this,&amp;nbsp;localAddress);
}

public&amp;nbsp;static&amp;nbsp;ChannelFuture&amp;nbsp;bind(Channel&amp;nbsp;channel,&amp;nbsp;SocketAddress&amp;nbsp;localAddress)&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ChannelFuture&amp;nbsp;future&amp;nbsp;=&amp;nbsp;future(channel);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;channel.getPipeline().sendDownstream(new&amp;nbsp;DownstreamChannelStateEvent(
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;channel,&amp;nbsp;future,&amp;nbsp;ChannelState.BOUND,&amp;nbsp;localAddress));
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;future;
}&lt;/pre&gt;

&lt;p&gt;sendDownstream,暂时没有能处理Downstream的handler,这个要交给Sink来处理&lt;/p&gt;
&lt;pre class=&quot;brush:java;toolbar:false;&quot;&gt;public&amp;nbsp;void&amp;nbsp;sendDownstream(ChannelEvent&amp;nbsp;e)&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;DefaultChannelHandlerContext&amp;nbsp;tail&amp;nbsp;=&amp;nbsp;getActualDownstreamContext(this.tail);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;(tail&amp;nbsp;==&amp;nbsp;null)&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;getSink().eventSunk(this,&amp;nbsp;e);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;sendDownstream(tail,&amp;nbsp;e);
}&lt;/pre&gt;
&lt;pre class=&quot;brush:java;toolbar:false;&quot;&gt;public&amp;nbsp;void&amp;nbsp;eventSunk(
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ChannelPipeline&amp;nbsp;pipeline,&amp;nbsp;ChannelEvent&amp;nbsp;e)&amp;nbsp;throws&amp;nbsp;Exception&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Channel&amp;nbsp;channel&amp;nbsp;=&amp;nbsp;e.getChannel();
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;(channel&amp;nbsp;instanceof&amp;nbsp;NioServerSocketChannel)&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;handleServerSocket(e);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&amp;nbsp;else&amp;nbsp;if&amp;nbsp;(channel&amp;nbsp;instanceof&amp;nbsp;NioSocketChannel)&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;handleAcceptedSocket(e);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
}&lt;/pre&gt;

&lt;p&gt;显然&lt;/p&gt;
&lt;pre class=&quot;brush:java;toolbar:false;&quot;&gt;private&amp;nbsp;static&amp;nbsp;void&amp;nbsp;handleServerSocket(ChannelEvent&amp;nbsp;e)&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ChannelStateEvent&amp;nbsp;event&amp;nbsp;=&amp;nbsp;(ChannelStateEvent)&amp;nbsp;e;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;NioServerSocketChannel&amp;nbsp;channel&amp;nbsp;=
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;(NioServerSocketChannel)&amp;nbsp;event.getChannel();
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ChannelFuture&amp;nbsp;future&amp;nbsp;=&amp;nbsp;event.getFuture();
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ChannelState&amp;nbsp;state&amp;nbsp;=&amp;nbsp;event.getState();
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Object&amp;nbsp;value&amp;nbsp;=&amp;nbsp;event.getValue();

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;switch&amp;nbsp;(state)&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;case&amp;nbsp;BOUND:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;(value&amp;nbsp;!=&amp;nbsp;null)&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;((NioServerBoss)&amp;nbsp;channel.boss).bind(channel,&amp;nbsp;future,&amp;nbsp;(SocketAddress)&amp;nbsp;value);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;break;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
}&lt;/pre&gt;

&lt;p&gt;channel是设置过boss的,在boss里面注册任务,这个任务是用来给boss线程的&lt;/p&gt;

&lt;pre class=&quot;brush:java;toolbar:false;&quot;&gt;void&amp;nbsp;bind(final&amp;nbsp;NioServerSocketChannel&amp;nbsp;channel,&amp;nbsp;final&amp;nbsp;ChannelFuture&amp;nbsp;future,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;final&amp;nbsp;SocketAddress&amp;nbsp;localAddress)&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;registerTask(new&amp;nbsp;RegisterTask(channel,&amp;nbsp;future,&amp;nbsp;localAddress));
}&lt;/pre&gt;

&lt;p&gt;首先要new一下registerTask,然后再注册&lt;/p&gt;

&lt;p&gt;在task队列里加入一个task,wakenUp设置为true,然后叫醒boss线程&lt;/p&gt;
&lt;pre class=&quot;brush:java;toolbar:false;&quot;&gt;protected&amp;nbsp;final&amp;nbsp;void&amp;nbsp;registerTask(Runnable&amp;nbsp;task)&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;taskQueue.add(task);

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Selector&amp;nbsp;selector&amp;nbsp;=&amp;nbsp;this.selector;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;(selector&amp;nbsp;!=&amp;nbsp;null)&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;(wakenUp.compareAndSet(false,&amp;nbsp;true))&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;selector.wakeup();
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
}&lt;/pre&gt;

&lt;p&gt;然后就要分2段来讨论了,一边boss线程睡醒要开始处理task,task.run(),来做真正的绑定&lt;/p&gt;

&lt;p&gt;一边主线程要继续添加addListener,然后继续处理newChannel之后的新建ChannelFuture来接收bindFuture的success事件,这是一个连续或是链式的异步调用,把bindFuture直接返回去究竟行不行,为什么要这么设计,而且写了这么多东西真正有用的就4句话,这究竟实在干什么,真的很优雅吗?不过这倒是一个典型的生产者消费者的模型&lt;/p&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;boss线程&quot;&gt;boss线程&lt;/h3&gt;

&lt;p&gt;这个future也就是之前bind(localAddress)产生的future,这个futur被扔进了DownstreamChannelStateEvent,放到了downstream里,sink接住,sink调用event里面的channel的boss的bind方法把这个future又传了出去,扔进了registerTask里面,然后这个registerTask被扔进了taskQueue里面,然后被boss线程拿出来,并给这个future设置了success&lt;/p&gt;

&lt;pre class=&quot;brush:java;toolbar:false;&quot;&gt;processTaskQueue();

final&amp;nbsp;Runnable&amp;nbsp;task&amp;nbsp;=&amp;nbsp;taskQueue.poll();
task.run();

//NioServerBoss$RegisterTask-&amp;gt;run()
public&amp;nbsp;void&amp;nbsp;run()&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;boolean&amp;nbsp;bound&amp;nbsp;=&amp;nbsp;false;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;boolean&amp;nbsp;registered&amp;nbsp;=&amp;nbsp;false;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;channel.socket.socket().bind(localAddress,&amp;nbsp;channel.getConfig().getBacklog());
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;bound&amp;nbsp;=&amp;nbsp;true;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;future.setSuccess();
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;fireChannelBound(channel,&amp;nbsp;channel.getLocalAddress());
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;channel.socket.register(selector,&amp;nbsp;SelectionKey.OP_ACCEPT,&amp;nbsp;channel);

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;registered&amp;nbsp;=&amp;nbsp;true;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
}&lt;/pre&gt;

&lt;p&gt;setSuccess很多操作和awaitUninterruptibly有共同之处&lt;/p&gt;

&lt;p&gt;设置done为true,并通知所用的listener&lt;/p&gt;

&lt;p&gt;**&lt;span style=&quot;color: rgb(192, 0, 0);&quot;&gt;这个存在一个时序的问题,究竟是boss线程先完成并设置success还是主线程先添加完addListener,使得DefaultChannel&lt;strong&gt;Future里面里面的firstListener不再为null影响着这个程序到底是怎么运行的,不过这个无论怎么运行都是对的**&amp;lt;/span&amp;gt;&lt;/strong&gt;&lt;span style=&quot;text-decoration: line-through;&quot;&gt;**&lt;span style=&quot;text-decoration: line-through; color: rgb(192, 0, 0);&quot;&gt;&lt;strong&gt;.运行大概5次有1次是主线程先跑完的**&amp;lt;/span&amp;gt;&lt;/strong&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;**&lt;span style=&quot;color: rgb(192, 0, 0);&quot;&gt;&lt;strong&gt;如果是主线程先跑完的这个notifyListeners就能直接运行,否则就什么都没发生**&amp;lt;/span&amp;gt;&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;brush:java;toolbar:false;&quot;&gt;public&amp;nbsp;boolean&amp;nbsp;setSuccess()&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;synchronized&amp;nbsp;(this)&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;(done)&amp;nbsp;return&amp;nbsp;false;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;done&amp;nbsp;=&amp;nbsp;true;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;(waiters&amp;nbsp;&amp;gt;&amp;nbsp;0)&amp;nbsp;notifyAll();
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;notifyListeners();
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;true;
}

private&amp;nbsp;void&amp;nbsp;notifyListeners()&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;(firstListener&amp;nbsp;!=&amp;nbsp;null)&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;notifyListener(firstListener);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;firstListener&amp;nbsp;=&amp;nbsp;null;

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;(otherListeners&amp;nbsp;!=&amp;nbsp;null)&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;for&amp;nbsp;(ChannelFutureListener&amp;nbsp;l:&amp;nbsp;otherListeners)&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;notifyListener(l);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;otherListeners&amp;nbsp;=&amp;nbsp;null;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
}

private&amp;nbsp;void&amp;nbsp;notifyListener(ChannelFutureListener&amp;nbsp;l)&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//回调
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;l.operationComplete(this);
}&lt;/pre&gt;

&lt;p&gt;不过boss被我debug了这么长时间肯定是主线程先跑完了,但是主线程现在不知道到哪了,估计在future.awaitUninterruptibly()等着呢&lt;/p&gt;

&lt;p&gt;事件完成回调之前addListener里面ChannelFutureListener的operationComplete&lt;/p&gt;

&lt;p&gt;这个bind(localAddress)产生的future是一个隐式的future,这个future在上述的过程中执行完成,被boss线程setSuccess&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;span style=&quot;color: rgb(192, 0, 0);&quot;&gt;然后在这个隐式的future的listener的operationComplete –&amp;gt;bindFuture.setSuccess()&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;span style=&quot;color: rgb(192, 0, 0);&quot;&gt;然后触发bindFuture的operationComplete,调用bfuture的setSuccess()&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;span style=&quot;color: rgb(192, 0, 0);&quot;&gt;然后future.awaitUninterruptibly()结束等待进入下一步&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;**&lt;span style=&quot;color: rgb(192, 0, 0);&quot;&gt;当我调试到&lt;strong&gt;bfuture的&lt;strong&gt;setSuccess时,会有waiters在等待,在notifyAll的时候,main线程结束等待并执行完成**&lt;/strong&gt;&amp;lt;/span&amp;gt;&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;&lt;span style=&quot;color: rgb(84, 141, 212);&quot;&gt;&lt;strong&gt;&lt;strong&gt;&lt;strong&gt;修改源代码,返回binder.bindFuture,不再创建&lt;strong&gt;bfuture,运行完全没问题,这应该算是为了不返回一个内部类的变量而作的优雅的选择吧**&lt;/strong&gt;&lt;/strong&gt;&lt;/strong&gt;&amp;lt;/span&amp;gt;&lt;/strong&gt;&lt;span style=&quot;color: rgb(192, 0, 0);&quot;&gt;&lt;strong&gt;&lt;strong&gt;
**&lt;/strong&gt;&amp;lt;/span&amp;gt;&lt;/strong&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;brush:java;toolbar:false;&quot;&gt;evt.getChannel().bind(localAddress).addListener(new&amp;nbsp;ChannelFutureListener()&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public&amp;nbsp;void&amp;nbsp;operationComplete(ChannelFuture&amp;nbsp;future)&amp;nbsp;throws&amp;nbsp;Exception&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;(future.isSuccess())&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;bindFuture.setSuccess();
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
});

public&amp;nbsp;synchronized&amp;nbsp;boolean&amp;nbsp;isSuccess()&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;done&amp;nbsp;&amp;amp;&amp;amp;&amp;nbsp;cause&amp;nbsp;==&amp;nbsp;null;
}&lt;/pre&gt;

&lt;pre class=&quot;brush:java;toolbar:false;&quot;&gt;final&amp;nbsp;ChannelFuture&amp;nbsp;bfuture&amp;nbsp;=&amp;nbsp;new&amp;nbsp;DefaultChannelFuture(channel,&amp;nbsp;false);
System.out.println(Thread.currentThread().getName()+&amp;quot;&amp;nbsp;:&amp;nbsp;bindFuture&amp;nbsp;addListener&amp;quot;);
binder.bindFuture.addListener(new&amp;nbsp;ChannelFutureListener()&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public&amp;nbsp;void&amp;nbsp;operationComplete(ChannelFuture&amp;nbsp;future)&amp;nbsp;throws&amp;nbsp;Exception&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;(future.isSuccess())&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;System.out.println(Thread.currentThread().getName()+&amp;quot;&amp;nbsp;:&amp;nbsp;bfuture&amp;nbsp;操作完成&amp;nbsp;回调setSuccess&amp;quot;);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;bfuture.setSuccess();
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&amp;nbsp;else&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp;Call&amp;nbsp;close&amp;nbsp;on&amp;nbsp;bind&amp;nbsp;failure
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;bfuture.getChannel().close();
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;bfuture.setFailure(future.getCause());
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
});
return&amp;nbsp;bfuture;&lt;/pre&gt;

&lt;p&gt;回到boss线程,boss线程把隐式的future.setSuccess之后调用了上述的一大串操作,然后boss在&lt;/p&gt;

&lt;pre class=&quot;brush:java;toolbar:false;&quot;&gt;fireChannelBound(channel,&amp;nbsp;channel.getLocalAddress());
channel.socket.register(selector,&amp;nbsp;SelectionKey.OP_ACCEPT,&amp;nbsp;channel);&lt;/pre&gt;

&lt;p&gt;之后就运行完成了准备回去睡觉了&lt;/p&gt;

&lt;p&gt;但binder并没有准备处理channelBound(ctx, evt)&lt;/p&gt;

&lt;p&gt;然后注册下就准备睡了&lt;/p&gt;

&lt;p&gt;这就是这4句话的执行过程和对应的时序分支&lt;/p&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;main线程&quot;&gt;&lt;strong&gt;main线程&lt;/strong&gt;&lt;/h3&gt;

&lt;p&gt;main线程在bind完了之后的动作**
**&lt;/p&gt;

&lt;p&gt;也就是这个&lt;/p&gt;

&lt;pre class=&quot;brush:java;toolbar:false;&quot;&gt;evt.getChannel().bind(localAddress).addListener(new&amp;nbsp;ChannelFutureListener()&lt;/pre&gt;

&lt;p&gt;addListener,就是判断这个future的done是否被设置成true,也就是说是否被setSuccess了(或是以其他的方式结束了)&lt;/p&gt;

&lt;p&gt;如果done为true,那么直接notifyListener()&lt;/p&gt;

&lt;p&gt;如果没有的话,就进入这个future的listener list,至于为什么有firstListener和otherListeners可能是出于性能的考虑吧&lt;/p&gt;

&lt;pre class=&quot;brush:java;toolbar:false;&quot;&gt;public&amp;nbsp;void&amp;nbsp;addListener(ChannelFutureListener&amp;nbsp;listener)&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;(listener&amp;nbsp;==&amp;nbsp;null)&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;throw&amp;nbsp;new&amp;nbsp;NullPointerException(&amp;quot;listener&amp;quot;);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;boolean&amp;nbsp;notifyNow&amp;nbsp;=&amp;nbsp;false;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;synchronized&amp;nbsp;(this)&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;(done)&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;notifyNow&amp;nbsp;=&amp;nbsp;true;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&amp;nbsp;else&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;(firstListener&amp;nbsp;==&amp;nbsp;null)&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;firstListener&amp;nbsp;=&amp;nbsp;listener;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&amp;nbsp;else&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;(otherListeners&amp;nbsp;==&amp;nbsp;null)&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;otherListeners&amp;nbsp;=&amp;nbsp;new&amp;nbsp;ArrayList&amp;lt;ChannelFutureListener&amp;gt;(1);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;otherListeners.add(listener);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;(listener&amp;nbsp;instanceof&amp;nbsp;ChannelFutureProgressListener)&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;(progressListeners&amp;nbsp;==&amp;nbsp;null)&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;progressListeners&amp;nbsp;=&amp;nbsp;new&amp;nbsp;ArrayList&amp;lt;ChannelFutureProgressListener&amp;gt;(1);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;progressListeners.add((ChannelFutureProgressListener)&amp;nbsp;listener);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;(notifyNow)&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;notifyListener(listener);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
}&lt;/pre&gt;

&lt;p&gt;主线程在添加了2个addListener之后,bind就结束了,进入bind外边的await等待&lt;/p&gt;

&lt;p&gt;在大部分情况,boss线程的wakeUp还是挺快的,addListener操作会直接进入notifyListener()&lt;/p&gt;

&lt;p&gt;**
**&lt;/p&gt;
</description>
          <pubDate>2017-07-03T00:00:00+08:00</pubDate>
          <link>https://asens.github.io/notes/Netty%E5%90%AF%E5%8A%A8%E6%B5%81%E7%A8%8B(4)</link>
          <guid isPermaLink="true">https://asens.github.io/notes/Netty%E5%90%AF%E5%8A%A8%E6%B5%81%E7%A8%8B(4)</guid>
        </item>
      
    
  </channel>
</rss>
