.markdown-body { color: #24292e; font-family: -apple-system, BlinkMacSystemFont, “Segoe UI”, Helvetica, Arial, sans-serif, “Apple Color Emoji”, “Segoe UI Emoji”, “Segoe UI Symbol”; font-size: 16px; line-height: 1.5 }
.markdown-body .pl-c { color: #6a737d }
.markdown-body .pl-c1,.markdown-body .pl-s .pl-v { color: #005cc5 }
.markdown-body .pl-e,.markdown-body .pl-en { color: #6f42c1 }
.markdown-body .pl-smi,.markdown-body .pl-s .pl-s1 { color: #24292e }
.markdown-body .pl-ent { color: #22863a }
.markdown-body .pl-k { color: #d73a49 }
.markdown-body .pl-s,.markdown-body .pl-pds,.markdown-body .pl-s .pl-pse .pl-s1,.markdown-body .pl-sr,.markdown-body .pl-sr .pl-cce,.markdown-body .pl-sr .pl-sre,.markdown-body .pl-sr .pl-sra { color: #032f62 }
.markdown-body .pl-v,.markdown-body .pl-smw { color: #e36209 }
.markdown-body .pl-bu { color: #b31d28 }
.markdown-body .pl-ii { color: #fafbfc; background-color: #b31d28 }
.markdown-body .pl-c2 { color: #fafbfc; background-color: #d73a49 }
.markdown-body .pl-c2::before { content: “^M” }
.markdown-body .pl-sr .pl-cce { font-weight: bold; color: #22863a }
.markdown-body .pl-ml { color: #735c0f }
.markdown-body .pl-mh,.markdown-body .pl-mh .pl-en,.markdown-body .pl-ms { font-weight: bold; color: #005cc5 }
.markdown-body .pl-mi { font-style: italic; color: #24292e }
.markdown-body .pl-mb { font-weight: bold; color: #24292e }
.markdown-body .pl-md { color: #b31d28; background-color: #ffeef0 }
.markdown-body .pl-mi1 { color: #22863a; background-color: #f0fff4 }
.markdown-body .pl-mc { color: #e36209; background-color: #ffebda }
.markdown-body .pl-mi2 { color: #f6f8fa; background-color: #005cc5 }
.markdown-body .pl-mdr { font-weight: bold; color: #6f42c1 }
.markdown-body .pl-ba { color: #586069 }
.markdown-body .pl-sg { color: #959da5 }
.markdown-body .pl-corl { text-decoration: underline; color: #032f62 }
.markdown-body .octicon { display: inline-block; vertical-align: text-top }
.markdown-body a { background-color: transparent }
.markdown-body a:active,.markdown-body a:hover { outline-width: 0 }
.markdown-body strong { font-weight: inherit }
.markdown-body strong { font-weight: bolder }
.markdown-body h1 { font-size: 2em; margin: 0.67em 0 }
.markdown-body img { border-style: none }
.markdown-body svg:not(:root) { overflow: hidden }
.markdown-body code,.markdown-body kbd,.markdown-body pre { font-family: monospace, monospace; font-size: 1em }
.markdown-body hr { height: 0; overflow: visible }
.markdown-body input { font: inherit; margin: 0 }
.markdown-body input { overflow: visible }
.markdown-body [type=”checkbox”] { padding: 0 }
.markdown-body * { }
.markdown-body input { font-family: inherit; font-size: inherit; line-height: inherit }
.markdown-body a { color: #0366d6; text-decoration: none }
.markdown-body a:hover { text-decoration: underline }
.markdown-body strong { font-weight: 600 }
.markdown-body hr { height: 0; margin: 15px 0; overflow: hidden; background: transparent; border: 0; border-bottom: 1px solid #dfe2e5 }
.markdown-body hr::before { display: table; content: “” }
.markdown-body hr::after { display: table; clear: both; content: “” }
.markdown-body table { border-spacing: 0; border-collapse: collapse }
.markdown-body td,.markdown-body th { padding: 0 }
.markdown-body h1,.markdown-body h2,.markdown-body h3,.markdown-body h4,.markdown-body h5,.markdown-body h6 { margin-top: 0; margin-bottom: 0 }
.markdown-body h1 { font-size: 32px; font-weight: 600 }
.markdown-body h2 { font-size: 24px; font-weight: 600 }
.markdown-body h3 { font-size: 20px; font-weight: 600 }
.markdown-body h4 { font-size: 16px; font-weight: 600 }
.markdown-body h5 { font-size: 14px; font-weight: 600 }
.markdown-body h6 { font-size: 12px; font-weight: 600 }
.markdown-body p { margin-top: 0; margin-bottom: 10px }
.markdown-body blockquote { margin: 0 }
.markdown-body ul,.markdown-body ol { padding-left: 0; margin-top: 0; margin-bottom: 0 }
.markdown-body ol ol,.markdown-body ul ol { list-style-type: lower-roman }
.markdown-body ul ul ol,.markdown-body ul ol ol,.markdown-body ol ul ol,.markdown-body ol ol ol { list-style-type: lower-alpha }
.markdown-body dd { margin-left: 0 }
.markdown-body code { font-family: “SFMono-Regular”, Consolas, “Liberation Mono”, Menlo, Courier, monospace; font-size: 12px }
.markdown-body pre { margin-top: 0; margin-bottom: 0; font: 12px “SFMono-Regular”, Consolas, “Liberation Mono”, Menlo, Courier, monospace }
.markdown-body .octicon { vertical-align: text-bottom }
.markdown-body .pl-0 { padding-left: 0 !important }
.markdown-body .pl-1 { padding-left: 4px !important }
.markdown-body .pl-2 { padding-left: 8px !important }
.markdown-body .pl-3 { padding-left: 16px !important }
.markdown-body .pl-4 { padding-left: 24px !important }
.markdown-body .pl-5 { padding-left: 32px !important }
.markdown-body .pl-6 { padding-left: 40px !important }
.markdown-body::before { display: table; content: “” }
.markdown-body::after { display: table; clear: both; content: “” }
.markdown-body>*:first-child { margin-top: 0 !important }
.markdown-body>*:last-child { margin-bottom: 0 !important }
.markdown-body a:not([href]) { color: inherit; text-decoration: none }
.markdown-body .anchor { float: left; padding-right: 4px; margin-left: -20px; line-height: 1 }
.markdown-body .anchor:focus { outline: none }
.markdown-body p,.markdown-body blockquote,.markdown-body ul,.markdown-body ol,.markdown-body dl,.markdown-body table,.markdown-body pre { margin-top: 0; margin-bottom: 16px }
.markdown-body hr { height: 0.25em; padding: 0; margin: 24px 0; background-color: #e1e4e8; border: 0 }
.markdown-body blockquote { padding: 0 1em; color: #6a737d; border-left: 0.25em solid #dfe2e5 }
.markdown-body blockquote>:first-child { margin-top: 0 }
.markdown-body blockquote>:last-child { margin-bottom: 0 }
.markdown-body kbd { display: inline-block; padding: 3px 5px; font-size: 11px; line-height: 10px; color: #444d56; vertical-align: middle; background-color: #fafbfc; border: solid 1px #c6cbd1; border-bottom-color: #959da5 }
.markdown-body h1,.markdown-body h2,.markdown-body h3,.markdown-body h4,.markdown-body h5,.markdown-body h6 { margin-top: 24px; margin-bottom: 16px; font-weight: 600; line-height: 1.25 }
.markdown-body h1 .octicon-link,.markdown-body h2 .octicon-link,.markdown-body h3 .octicon-link,.markdown-body h4 .octicon-link,.markdown-body h5 .octicon-link,.markdown-body h6 .octicon-link { color: #1b1f23; vertical-align: middle; visibility: hidden }
.markdown-body h1:hover .anchor,.markdown-body h2:hover .anchor,.markdown-body h3:hover .anchor,.markdown-body h4:hover .anchor,.markdown-body h5:hover .anchor,.markdown-body h6:hover .anchor { text-decoration: none }
.markdown-body h1:hover .anchor .octicon-link,.markdown-body h2:hover .anchor .octicon-link,.markdown-body h3:hover .anchor .octicon-link,.markdown-body h4:hover .anchor .octicon-link,.markdown-body h5:hover .anchor .octicon-link,.markdown-body h6:hover .anchor .octicon-link { visibility: visible }
.markdown-body h1 { padding-bottom: 0.3em; font-size: 2em; border-bottom: 1px solid #eaecef }
.markdown-body h2 { padding-bottom: 0.3em; font-size: 1.5em; border-bottom: 1px solid #eaecef }
.markdown-body h3 { font-size: 1.25em }
.markdown-body h4 { font-size: 1em }
.markdown-body h5 { font-size: 0.875em }
.markdown-body h6 { font-size: 0.85em; color: #6a737d }
.markdown-body ul,.markdown-body ol { padding-left: 2em }
.markdown-body ul ul,.markdown-body ul ol,.markdown-body ol ol,.markdown-body ol ul { margin-top: 0; margin-bottom: 0 }
.markdown-body li>p { margin-top: 16px }
.markdown-body li+li { margin-top: 0.25em }
.markdown-body dl { padding: 0 }
.markdown-body dl dt { padding: 0; margin-top: 16px; font-size: 1em; font-style: italic; font-weight: 600 }
.markdown-body dl dd { padding: 0 16px; margin-bottom: 16px }
.markdown-body table { display: block; width: 100%; overflow: auto }
.markdown-body table th { font-weight: 600 }
.markdown-body table th,.markdown-body table td { padding: 6px 13px; border: 1px solid #dfe2e5 }
.markdown-body table tr { background-color: #fff; border-top: 1px solid #c6cbd1 }
.markdown-body table tr:nth-child(2n) { background-color: #f6f8fa }
.markdown-body img { max-width: 100%; background-color: #fff }
.markdown-body code { padding: 0; padding-top: 0.2em; padding-bottom: 0.2em; margin: 0; font-size: 85%; background-color: rgba(27,31,35,0.05) }
.markdown-body code::before,.markdown-body code::after { letter-spacing: -0.2em; content: ” ” }
.markdown-body pre { }
.markdown-body pre>code { padding: 0; margin: 0; font-size: 100%; white-space: pre; background: transparent; border: 0 }
.markdown-body .highlight { margin-bottom: 16px }
.markdown-body .highlight pre { margin-bottom: 0 }
.markdown-body .highlight pre,.markdown-body pre { padding: 16px; overflow: auto; font-size: 85%; line-height: 1.45; background-color: #f6f8fa }
.markdown-body pre code { display: inline; max-width: auto; padding: 0; margin: 0; overflow: visible; line-height: inherit; background-color: transparent; border: 0 }
.markdown-body pre code::before,.markdown-body pre code::after { content: normal }
.markdown-body .full-commit .btn-outline:not(:disabled):hover { color: #005cc5; border-color: #005cc5 }
.markdown-body kbd { display: inline-block; padding: 3px 5px; font: 11px “SFMono-Regular”, Consolas, “Liberation Mono”, Menlo, Courier, monospace; line-height: 10px; color: #444d56; vertical-align: middle; background-color: #fafbfc; border: solid 1px #d1d5da; border-bottom-color: #c6cbd1 }
.markdown-body :checked+.radio-label { position: relative; z-index: 1; border-color: #0366d6 }
.markdown-body .task-list-item { list-style-type: none }
.markdown-body .task-list-item+.task-list-item { margin-top: 3px }
.markdown-body .task-list-item input { margin: 0 0.2em 0.25em -1.6em; vertical-align: middle }
.markdown-body hr { border-bottom-color: #eee }
.hljs { display: block; padding: 0.5em; color: #333; background: #f8f8f8 }
.hljs-comment,.hljs-quote { color: #998; font-style: italic }
.hljs-keyword,.hljs-selector-tag,.hljs-subst { color: #333; font-weight: bold }
.hljs-number,.hljs-literal,.hljs-variable,.hljs-template-variable,.hljs-tag .hljs-attr { color: #008080 }
.hljs-string,.hljs-doctag { color: #d14 }
.hljs-title,.hljs-section,.hljs-selector-id { color: #900; font-weight: bold }
.hljs-subst { font-weight: normal }
.hljs-type,.hljs-class .hljs-title { color: #458; font-weight: bold }
.hljs-tag,.hljs-name,.hljs-attribute { color: #000080; font-weight: normal }
.hljs-regexp,.hljs-link { color: #009926 }
.hljs-symbol,.hljs-bullet { color: #990073 }
.hljs-built_in,.hljs-builtin-name { color: #0086b3 }
.hljs-meta { color: #999; font-weight: bold }
.hljs-deletion { background: #fdd }
.hljs-addition { background: #dfd }
.hljs-emphasis { font-style: italic }
.hljs-strong { font-weight: bold }
.mermaid .label { color: #333 }
.node rect,.node circle,.node ellipse,.node polygon { }
.edgePath .path { }
.edgeLabel { background-color: #e8e8e8 }
.cluster rect { }
.cluster text { }
.actor { }
text.actor { }
.actor-line { }
.messageLine0 { }
.messageLine1 { }
#arrowhead { }
#crosshead path { }
.messageText { }
.labelBox { }
.labelText { }
.loopText { }
.loopLine { }
.note { }
.noteText { font-family: “trebuchet ms”, verdana, arial; font-size: 14px }
.section { opacity: 0.2 }
.section0 { }
.section2 { }
.section1,.section3 { opacity: 0.2 }
.sectionTitle0 { }
.sectionTitle1 { }
.sectionTitle2 { }
.sectionTitle3 { }
.sectionTitle { font-size: 11px }
.grid .tick { opacity: 0.3 }
.grid path { }
.today { }
.task { }
.taskText { font-size: 11px }
.taskTextOutsideRight { font-size: 11px }
.taskTextOutsideLeft { font-size: 11px }
.taskText0,.taskText1,.taskText2,.taskText3 { }
.task0,.task1,.task2,.task3 { }
.taskTextOutside0,.taskTextOutside2 { }
.taskTextOutside1,.taskTextOutside3 { }
.active0,.active1,.active2,.active3 { }
.activeText0,.activeText1,.activeText2,.activeText3 { }
.done0,.done1,.done2,.done3 { }
.doneText0,.doneText1,.doneText2,.doneText3 { }
.crit0,.crit1,.crit2,.crit3 { }
.activeCrit0,.activeCrit1,.activeCrit2,.activeCrit3 { }
.doneCrit0,.doneCrit1,.doneCrit2,.doneCrit3 { cursor: pointer }
.doneCritText0,.doneCritText1,.doneCritText2,.doneCritText3 { }
.activeCritText0,.activeCritText1,.activeCritText2,.activeCritText3 { }
.titleText { font-size: 18px }
.node text { font-family: “trebuchet ms”, verdana, arial; font-size: 14px }
div.mermaidTooltip { position: absolute; text-align: center; max-width: 200px; padding: 2px; font-family: “trebuchet ms”, verdana, arial; font-size: 12px; background: #ffffde; border: 1px solid #aaaa33; z-index: 100 }
.katex-display { display: block; margin: 1em 0; text-align: center }
.katex .base,.katex .katex-html,.katex .strut { display: inline-block }
.katex-display>.katex { display: inline-block; text-align: initial }
.katex { font: 400 1.21em KaTeX_Main, Times New Roman, serif; line-height: 1.2; white-space: nowrap; text-indent: 0 }
.katex * { }
.katex .katex-mathml { position: absolute; clip: rect(1px,1px,1px,1px); padding: 0; border: 0; height: 1px; width: 1px; overflow: hidden }
.katex .base { position: relative }
.katex .mathrm { font-style: normal }
.katex .mainit,.katex .mathit,.katex .textit { font-style: italic }
.katex .mathit { font-family: KaTeX_Math }
.katex .mathbf { font-family: KaTeX_Main; font-weight: 700 }
.katex .amsrm,.katex .mathbb { font-family: KaTeX_AMS }
.katex .mathcal { font-family: KaTeX_Caligraphic }
.katex .mathfrak { font-family: KaTeX_Fraktur }
.katex .mathtt { font-family: KaTeX_Typewriter }
.katex .mathscr { font-family: KaTeX_Script }
.katex .mathsf { font-family: KaTeX_SansSerif }
.katex .mainit { font-family: KaTeX_Main }
.katex .mainrm { font-family: KaTeX_Main; font-style: normal }
.katex .mord+.mop { margin-left: .16667em }
.katex .mord+.mbin { margin-left: .22222em }
.katex .mord+.mrel { margin-left: .27778em }
.katex .mop+.mop,.katex .mop+.mord,.katex .mord+.minner { margin-left: .16667em }
.katex .mop+.mrel { margin-left: .27778em }
.katex .mop+.minner { margin-left: .16667em }
.katex .mbin+.minner,.katex .mbin+.mop,.katex .mbin+.mopen,.katex .mbin+.mord { margin-left: .22222em }
.katex .mrel+.minner,.katex .mrel+.mop,.katex .mrel+.mopen,.katex .mrel+.mord { margin-left: .27778em }
.katex .mclose+.mop { margin-left: .16667em }
.katex .mclose+.mbin { margin-left: .22222em }
.katex .mclose+.mrel { margin-left: .27778em }
.katex .mclose+.minner,.katex .minner+.mop,.katex .minner+.mord,.katex .mpunct+.mclose,.katex .mpunct+.minner,.katex .mpunct+.mop,.katex .mpunct+.mopen,.katex .mpunct+.mord,.katex .mpunct+.mpunct,.katex .mpunct+.mrel { margin-left: .16667em }
.katex .minner+.mbin { margin-left: .22222em }
.katex .minner+.mrel { margin-left: .27778em }
.katex .minner+.minner,.katex .minner+.mopen,.katex .minner+.mpunct { margin-left: .16667em }
.katex .mbin.mtight,.katex .mclose.mtight,.katex .minner.mtight,.katex .mop.mtight,.katex .mopen.mtight,.katex .mord.mtight,.katex .mpunct.mtight,.katex .mrel.mtight { margin-left: 0 }
.katex .mclose+.mop.mtight,.katex .minner+.mop.mtight,.katex .mop+.mop.mtight,.katex .mop+.mord.mtight,.katex .mord+.mop.mtight { margin-left: .16667em }
.katex .vlist-t { display: inline-table; table-layout: fixed }
.katex .vlist-r { display: table-row }
.katex .vlist { display: table-cell; vertical-align: bottom; position: relative }
.katex .vlist>span { display: block; height: 0; position: relative }
.katex .vlist>span>span { display: inline-block }
.katex .vlist>span>.pstrut { overflow: hidden; width: 0 }
.katex .vlist-t2 { margin-right: -2px }
.katex .vlist-s { display: table-cell; vertical-align: bottom; font-size: 1px; width: 2px }
.katex .fontsize-ensurer,.katex .llap>.fix,.katex .mfrac .frac-line,.katex .mspace,.katex .mtable .arraycolsep,.katex .mtable .vertical-separator,.katex .nulldelimiter,.katex .rlap>.fix,.katex .rule,.katex .sizing { display: inline-block }
.katex .msupsub { text-align: left }
.katex .accent>.vlist-t,.katex .mfrac>span>span,.katex .mtable .col-align-c>.vlist-t,.katex .op-limits>.vlist-t { text-align: center }
.katex .mfrac .frac-line { width: 100%; border-bottom-style: solid }
.katex .mspace.negativethinspace { margin-left: -.16667em }
.katex .mspace.thinspace { width: .16667em }
.katex .mspace.negativemediumspace { margin-left: -.22222em }
.katex .mspace.mediumspace { width: .22222em }
.katex .mspace.thickspace { width: .27778em }
.katex .mspace.sixmuspace { width: .333333em }
.katex .mspace.eightmuspace { width: .444444em }
.katex .mspace.enspace { width: .5em }
.katex .mspace.twelvemuspace { width: .666667em }
.katex .mspace.quad { width: 1em }
.katex .mspace.qquad { width: 2em }
.katex .llap,.katex .rlap { width: 0; position: relative }
.katex .llap>.inner,.katex .rlap>.inner { position: absolute }
.katex .llap>.inner { right: 0 }
.katex .rlap>.inner { left: 0 }
.katex .katex-logo .a { font-size: .75em; margin-left: -.32em; position: relative; top: -.2em }
.katex .katex-logo .t { margin-left: -.23em }
.katex .katex-logo .e { margin-left: -.1667em; position: relative; top: .2155em }
.katex .katex-logo .x { margin-left: -.125em }
.katex .rule { border: 0 solid; position: relative }
.katex .overline .overline-line,.katex .underline .underline-line { display: inline-block; width: 100%; border-bottom-style: solid }
.katex .sqrt>.root { margin-left: .27777778em; margin-right: -.55555556em }
.katex .fontsize-ensurer.reset-size1.size1,.katex .sizing.reset-size1.size1 { font-size: 1em }
.katex .fontsize-ensurer.reset-size1.size2,.katex .sizing.reset-size1.size2 { font-size: 1.2em }
.katex .fontsize-ensurer.reset-size1.size3,.katex .sizing.reset-size1.size3 { font-size: 1.4em }
.katex .fontsize-ensurer.reset-size1.size4,.katex .sizing.reset-size1.size4 { font-size: 1.6em }
.katex .fontsize-ensurer.reset-size1.size5,.katex .sizing.reset-size1.size5 { font-size: 1.8em }
.katex .fontsize-ensurer.reset-size1.size6,.katex .sizing.reset-size1.size6 { font-size: 2em }
.katex .fontsize-ensurer.reset-size1.size7,.katex .sizing.reset-size1.size7 { font-size: 2.4em }
.katex .fontsize-ensurer.reset-size1.size8,.katex .sizing.reset-size1.size8 { font-size: 2.88em }
.katex .fontsize-ensurer.reset-size1.size9,.katex .sizing.reset-size1.size9 { font-size: 3.456em }
.katex .fontsize-ensurer.reset-size1.size10,.katex .sizing.reset-size1.size10 { font-size: 4.148em }
.katex .fontsize-ensurer.reset-size1.size11,.katex .sizing.reset-size1.size11 { font-size: 4.976em }
.katex .fontsize-ensurer.reset-size2.size1,.katex .sizing.reset-size2.size1 { font-size: .83333333em }
.katex .fontsize-ensurer.reset-size2.size2,.katex .sizing.reset-size2.size2 { font-size: 1em }
.katex .fontsize-ensurer.reset-size2.size3,.katex .sizing.reset-size2.size3 { font-size: 1.16666667em }
.katex .fontsize-ensurer.reset-size2.size4,.katex .sizing.reset-size2.size4 { font-size: 1.33333333em }
.katex .fontsize-ensurer.reset-size2.size5,.katex .sizing.reset-size2.size5 { font-size: 1.5em }
.katex .fontsize-ensurer.reset-size2.size6,.katex .sizing.reset-size2.size6 { font-size: 1.66666667em }
.katex .fontsize-ensurer.reset-size2.size7,.katex .sizing.reset-size2.size7 { font-size: 2em }
.katex .fontsize-ensurer.reset-size2.size8,.katex .sizing.reset-size2.size8 { font-size: 2.4em }
.katex .fontsize-ensurer.reset-size2.size9,.katex .sizing.reset-size2.size9 { font-size: 2.88em }
.katex .fontsize-ensurer.reset-size2.size10,.katex .sizing.reset-size2.size10 { font-size: 3.45666667em }
.katex .fontsize-ensurer.reset-size2.size11,.katex .sizing.reset-size2.size11 { font-size: 4.14666667em }
.katex .fontsize-ensurer.reset-size3.size1,.katex .sizing.reset-size3.size1 { font-size: .71428571em }
.katex .fontsize-ensurer.reset-size3.size2,.katex .sizing.reset-size3.size2 { font-size: .85714286em }
.katex .fontsize-ensurer.reset-size3.size3,.katex .sizing.reset-size3.size3 { font-size: 1em }
.katex .fontsize-ensurer.reset-size3.size4,.katex .sizing.reset-size3.size4 { font-size: 1.14285714em }
.katex .fontsize-ensurer.reset-size3.size5,.katex .sizing.reset-size3.size5 { font-size: 1.28571429em }
.katex .fontsize-ensurer.reset-size3.size6,.katex .sizing.reset-size3.size6 { font-size: 1.42857143em }
.katex .fontsize-ensurer.reset-size3.size7,.katex .sizing.reset-size3.size7 { font-size: 1.71428571em }
.katex .fontsize-ensurer.reset-size3.size8,.katex .sizing.reset-size3.size8 { font-size: 2.05714286em }
.katex .fontsize-ensurer.reset-size3.size9,.katex .sizing.reset-size3.size9 { font-size: 2.46857143em }
.katex .fontsize-ensurer.reset-size3.size10,.katex .sizing.reset-size3.size10 { font-size: 2.96285714em }
.katex .fontsize-ensurer.reset-size3.size11,.katex .sizing.reset-size3.size11 { font-size: 3.55428571em }
.katex .fontsize-ensurer.reset-size4.size1,.katex .sizing.reset-size4.size1 { font-size: .625em }
.katex .fontsize-ensurer.reset-size4.size2,.katex .sizing.reset-size4.size2 { font-size: .75em }
.katex .fontsize-ensurer.reset-size4.size3,.katex .sizing.reset-size4.size3 { font-size: .875em }
.katex .fontsize-ensurer.reset-size4.size4,.katex .sizing.reset-size4.size4 { font-size: 1em }
.katex .fontsize-ensurer.reset-size4.size5,.katex .sizing.reset-size4.size5 { font-size: 1.125em }
.katex .fontsize-ensurer.reset-size4.size6,.katex .sizing.reset-size4.size6 { font-size: 1.25em }
.katex .fontsize-ensurer.reset-size4.size7,.katex .sizing.reset-size4.size7 { font-size: 1.5em }
.katex .fontsize-ensurer.reset-size4.size8,.katex .sizing.reset-size4.size8 { font-size: 1.8em }
.katex .fontsize-ensurer.reset-size4.size9,.katex .sizing.reset-size4.size9 { font-size: 2.16em }
.katex .fontsize-ensurer.reset-size4.size10,.katex .sizing.reset-size4.size10 { font-size: 2.5925em }
.katex .fontsize-ensurer.reset-size4.size11,.katex .sizing.reset-size4.size11 { font-size: 3.11em }
.katex .fontsize-ensurer.reset-size5.size1,.katex .sizing.reset-size5.size1 { font-size: .55555556em }
.katex .fontsize-ensurer.reset-size5.size2,.katex .sizing.reset-size5.size2 { font-size: .66666667em }
.katex .fontsize-ensurer.reset-size5.size3,.katex .sizing.reset-size5.size3 { font-size: .77777778em }
.katex .fontsize-ensurer.reset-size5.size4,.katex .sizing.reset-size5.size4 { font-size: .88888889em }
.katex .fontsize-ensurer.reset-size5.size5,.katex .sizing.reset-size5.size5 { font-size: 1em }
.katex .fontsize-ensurer.reset-size5.size6,.katex .sizing.reset-size5.size6 { font-size: 1.11111111em }
.katex .fontsize-ensurer.reset-size5.size7,.katex .sizing.reset-size5.size7 { font-size: 1.33333333em }
.katex .fontsize-ensurer.reset-size5.size8,.katex .sizing.reset-size5.size8 { font-size: 1.6em }
.katex .fontsize-ensurer.reset-size5.size9,.katex .sizing.reset-size5.size9 { font-size: 1.92em }
.katex .fontsize-ensurer.reset-size5.size10,.katex .sizing.reset-size5.size10 { font-size: 2.30444444em }
.katex .fontsize-ensurer.reset-size5.size11,.katex .sizing.reset-size5.size11 { font-size: 2.76444444em }
.katex .fontsize-ensurer.reset-size6.size1,.katex .sizing.reset-size6.size1 { font-size: .5em }
.katex .fontsize-ensurer.reset-size6.size2,.katex .sizing.reset-size6.size2 { font-size: .6em }
.katex .fontsize-ensurer.reset-size6.size3,.katex .sizing.reset-size6.size3 { font-size: .7em }
.katex .fontsize-ensurer.reset-size6.size4,.katex .sizing.reset-size6.size4 { font-size: .8em }
.katex .fontsize-ensurer.reset-size6.size5,.katex .sizing.reset-size6.size5 { font-size: .9em }
.katex .fontsize-ensurer.reset-size6.size6,.katex .sizing.reset-size6.size6 { font-size: 1em }
.katex .fontsize-ensurer.reset-size6.size7,.katex .sizing.reset-size6.size7 { font-size: 1.2em }
.katex .fontsize-ensurer.reset-size6.size8,.katex .sizing.reset-size6.size8 { font-size: 1.44em }
.katex .fontsize-ensurer.reset-size6.size9,.katex .sizing.reset-size6.size9 { font-size: 1.728em }
.katex .fontsize-ensurer.reset-size6.size10,.katex .sizing.reset-size6.size10 { font-size: 2.074em }
.katex .fontsize-ensurer.reset-size6.size11,.katex .sizing.reset-size6.size11 { font-size: 2.488em }
.katex .fontsize-ensurer.reset-size7.size1,.katex .sizing.reset-size7.size1 { font-size: .41666667em }
.katex .fontsize-ensurer.reset-size7.size2,.katex .sizing.reset-size7.size2 { font-size: .5em }
.katex .fontsize-ensurer.reset-size7.size3,.katex .sizing.reset-size7.size3 { font-size: .58333333em }
.katex .fontsize-ensurer.reset-size7.size4,.katex .sizing.reset-size7.size4 { font-size: .66666667em }
.katex .fontsize-ensurer.reset-size7.size5,.katex .sizing.reset-size7.size5 { font-size: .75em }
.katex .fontsize-ensurer.reset-size7.size6,.katex .sizing.reset-size7.size6 { font-size: .83333333em }
.katex .fontsize-ensurer.reset-size7.size7,.katex .sizing.reset-size7.size7 { font-size: 1em }
.katex .fontsize-ensurer.reset-size7.size8,.katex .sizing.reset-size7.size8 { font-size: 1.2em }
.katex .fontsize-ensurer.reset-size7.size9,.katex .sizing.reset-size7.size9 { font-size: 1.44em }
.katex .fontsize-ensurer.reset-size7.size10,.katex .sizing.reset-size7.size10 { font-size: 1.72833333em }
.katex .fontsize-ensurer.reset-size7.size11,.katex .sizing.reset-size7.size11 { font-size: 2.07333333em }
.katex .fontsize-ensurer.reset-size8.size1,.katex .sizing.reset-size8.size1 { font-size: .34722222em }
.katex .fontsize-ensurer.reset-size8.size2,.katex .sizing.reset-size8.size2 { font-size: .41666667em }
.katex .fontsize-ensurer.reset-size8.size3,.katex .sizing.reset-size8.size3 { font-size: .48611111em }
.katex .fontsize-ensurer.reset-size8.size4,.katex .sizing.reset-size8.size4 { font-size: .55555556em }
.katex .fontsize-ensurer.reset-size8.size5,.katex .sizing.reset-size8.size5 { font-size: .625em }
.katex .fontsize-ensurer.reset-size8.size6,.katex .sizing.reset-size8.size6 { font-size: .69444444em }
.katex .fontsize-ensurer.reset-size8.size7,.katex .sizing.reset-size8.size7 { font-size: .83333333em }
.katex .fontsize-ensurer.reset-size8.size8,.katex .sizing.reset-size8.size8 { font-size: 1em }
.katex .fontsize-ensurer.reset-size8.size9,.katex .sizing.reset-size8.size9 { font-size: 1.2em }
.katex .fontsize-ensurer.reset-size8.size10,.katex .sizing.reset-size8.size10 { font-size: 1.44027778em }
.katex .fontsize-ensurer.reset-size8.size11,.katex .sizing.reset-size8.size11 { font-size: 1.72777778em }
.katex .fontsize-ensurer.reset-size9.size1,.katex .sizing.reset-size9.size1 { font-size: .28935185em }
.katex .fontsize-ensurer.reset-size9.size2,.katex .sizing.reset-size9.size2 { font-size: .34722222em }
.katex .fontsize-ensurer.reset-size9.size3,.katex .sizing.reset-size9.size3 { font-size: .40509259em }
.katex .fontsize-ensurer.reset-size9.size4,.katex .sizing.reset-size9.size4 { font-size: .46296296em }
.katex .fontsize-ensurer.reset-size9.size5,.katex .sizing.reset-size9.size5 { font-size: .52083333em }
.katex .fontsize-ensurer.reset-size9.size6,.katex .sizing.reset-size9.size6 { font-size: .5787037em }
.katex .fontsize-ensurer.reset-size9.size7,.katex .sizing.reset-size9.size7 { font-size: .69444444em }
.katex .fontsize-ensurer.reset-size9.size8,.katex .sizing.reset-size9.size8 { font-size: .83333333em }
.katex .fontsize-ensurer.reset-size9.size9,.katex .sizing.reset-size9.size9 { font-size: 1em }
.katex .fontsize-ensurer.reset-size9.size10,.katex .sizing.reset-size9.size10 { font-size: 1.20023148em }
.katex .fontsize-ensurer.reset-size9.size11,.katex .sizing.reset-size9.size11 { font-size: 1.43981481em }
.katex .fontsize-ensurer.reset-size10.size1,.katex .sizing.reset-size10.size1 { font-size: .24108004em }
.katex .fontsize-ensurer.reset-size10.size2,.katex .sizing.reset-size10.size2 { font-size: .28929605em }
.katex .fontsize-ensurer.reset-size10.size3,.katex .sizing.reset-size10.size3 { font-size: .33751205em }
.katex .fontsize-ensurer.reset-size10.size4,.katex .sizing.reset-size10.size4 { font-size: .38572806em }
.katex .fontsize-ensurer.reset-size10.size5,.katex .sizing.reset-size10.size5 { font-size: .43394407em }
.katex .fontsize-ensurer.reset-size10.size6,.katex .sizing.reset-size10.size6 { font-size: .48216008em }
.katex .fontsize-ensurer.reset-size10.size7,.katex .sizing.reset-size10.size7 { font-size: .57859209em }
.katex .fontsize-ensurer.reset-size10.size8,.katex .sizing.reset-size10.size8 { font-size: .69431051em }
.katex .fontsize-ensurer.reset-size10.size9,.katex .sizing.reset-size10.size9 { font-size: .83317261em }
.katex .fontsize-ensurer.reset-size10.size10,.katex .sizing.reset-size10.size10 { font-size: 1em }
.katex .fontsize-ensurer.reset-size10.size11,.katex .sizing.reset-size10.size11 { font-size: 1.19961427em }
.katex .fontsize-ensurer.reset-size11.size1,.katex .sizing.reset-size11.size1 { font-size: .20096463em }
.katex .fontsize-ensurer.reset-size11.size2,.katex .sizing.reset-size11.size2 { font-size: .24115756em }
.katex .fontsize-ensurer.reset-size11.size3,.katex .sizing.reset-size11.size3 { font-size: .28135048em }
.katex .fontsize-ensurer.reset-size11.size4,.katex .sizing.reset-size11.size4 { font-size: .32154341em }
.katex .fontsize-ensurer.reset-size11.size5,.katex .sizing.reset-size11.size5 { font-size: .36173633em }
.katex .fontsize-ensurer.reset-size11.size6,.katex .sizing.reset-size11.size6 { font-size: .40192926em }
.katex .fontsize-ensurer.reset-size11.size7,.katex .sizing.reset-size11.size7 { font-size: .48231511em }
.katex .fontsize-ensurer.reset-size11.size8,.katex .sizing.reset-size11.size8 { font-size: .57877814em }
.katex .fontsize-ensurer.reset-size11.size9,.katex .sizing.reset-size11.size9 { font-size: .69453376em }
.katex .fontsize-ensurer.reset-size11.size10,.katex .sizing.reset-size11.size10 { font-size: .83360129em }
.katex .fontsize-ensurer.reset-size11.size11,.katex .sizing.reset-size11.size11 { font-size: 1em }
.katex .delimsizing.size1 { font-family: KaTeX_Size1 }
.katex .delimsizing.size2 { font-family: KaTeX_Size2 }
.katex .delimsizing.size3 { font-family: KaTeX_Size3 }
.katex .delimsizing.size4 { font-family: KaTeX_Size4 }
.katex .delimsizing.mult .delim-size1>span { font-family: KaTeX_Size1 }
.katex .delimsizing.mult .delim-size4>span { font-family: KaTeX_Size4 }
.katex .nulldelimiter { width: .12em }
.katex .delimcenter,.katex .op-symbol { position: relative }
.katex .op-symbol.small-op { font-family: KaTeX_Size1 }
.katex .op-symbol.large-op { font-family: KaTeX_Size2 }
.katex .accent .accent-body>span { width: 0 }
.katex .accent .accent-body.accent-vec>span { position: relative; left: .326em }
.katex .accent .accent-body.accent-hungarian>span { position: relative; left: .25em }
.katex .mtable .vertical-separator { margin: 0 -.025em; border-right: .05em solid #000 }
.katex .stretchy,.katex svg { width: 100%; display: block }
.katex .mtable .col-align-l>.vlist-t { text-align: left }
.katex .mtable .col-align-r>.vlist-t { text-align: right }
.katex .svg-align { text-align: left }
.katex svg { position: absolute }
.katex svg path { }
.katex svg line { }
.katex .stretchy::after,.katex .stretchy::before { content: “” }
.katex .x-arrow-pad { padding: 0 .5em }
.katex .mover,.katex .munder,.katex .x-arrow { text-align: center }
.katex .boxpad { padding: 0 .3em }
.katex .fbox { border: .04em solid #000 }
.katex .cancel-pad { padding: 0 .2em }
.katex .cancel-lap+.mbin,.katex .cancel-lap+.mord,.katex .cancel-lap+.msupsub,.katex .mbin+.cancel-lap,.katex .mord+.cancel-lap { margin-left: -.2em }
.katex .sout { border-bottom-style: solid; border-bottom-width: .08em }
body { margin: 0; padding: 0 }
.markdown-body { min-width: 256px; max-width: 978px; margin: 0 auto; padding: 20px; font-size: 14px; font-family: “-apple-system”, BlinkMacSystemFont, “微软雅黑”, “PingFang SC”, Helvetica, Tahoma, Arial, “Hiragino Sans GB”, “Microsoft YaHei”, SimSun, “宋体”, Heiti, “黑体”, sans-serif }
.markdown-body h1 { font-size: 2.25em }
.markdown-body h2 { font-size: 1.75em }
.markdown-body h3 { font-size: 1.5em }
.markdown-body h4 { font-size: 1.25em }
.markdown-body h5,.markdown-body h6 { font-size: 1em }
.markdown-body pre>code { font-family: “SFMono-Regular”, Consolas, “Liberation Mono”, Menlo, Courier, monospace, sans-serif }
.markdown-body pre>code .zh-hans { font-family: “Microsoft YaHei”, “微软雅黑”, SimSun, sans-serif }
div.mermaid { text-align: center }
hr.footnotes-sep { margin: 64px 0 32px 0; height: 1px }
.footnotes { font-size: 90%; padding-left: 16px }
li.footnote-item>p { margin: 8px 0 }
.success,.info,.warning,.danger { padding: 15px; margin-bottom: 20px; border: 1px solid transparent }
.success>p:last-child,.info>p:last-child,.warning>p:last-child,.danger>p:last-child { margin-bottom: 0 }
.success { color: #3c763d; background-color: #dff0d8; border-color: #d6e9c6 }
.info { color: #31708f; background-color: #d9edf7; border-color: #bce8f1 }
.warning { color: #8a6d3b; background-color: #fcf8e3; border-color: #faebcc }
.danger { color: #a94442; background-color: #f2dede; border-color: #ebccd1 }
abbr[title] { cursor: help; border-bottom: 1px dotted #777 }
ul.table-of-contents { list-style-type: none }
ul.table-of-contents li { margin: 4px 0 }
.markdown-body table { width: auto; display: table }
.markdown-body table td,.markdown-body table th { }
.markdown-body.ace_search .highlight pre,.markdown-body.ace_search pre { overflow: visible !important; width: fit-content !important }

概述

spring 的核心依赖注入:创建应用对象之间协作关系的行为称为装配(wiring),他有以下几种方式:

  • 自动装配(结合注解)
  • Java中显示的配置
  • 在xml中显示的配置

这三个方案,选哪一个都是可以的,能用自动配置的就有自动配置,对于一些框架的配置我们不能修改别人的源码,必要的xml显示配置也是必要的,而且我们也可以三个方案同时使用,一些Bean自动装配,一些Bean Java配置,一些Bean xml配置。 对于显示配置,多少有些不方便还是自动装配最简便,所以我们先讲第一个自动化配置

创建项目

我们首先新建一个meavn项目,我这里用的是idea,推荐大家使用,超爽的开发工具。 添加spring 和 test需要的依赖

 <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.11</version>
      <scope>test</scope>
    </dependency>

    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>3.2.0.RELEASE</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-test</artifactId>
      <version>3.2.0.RELEASE</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-beans</artifactId>
      <version>3.2.0.RELEASE</version>
      <type>jar</type>
    </dependency>

源码均在github上可以获取,地址会在文末给出,欢迎加Start

自动化配置

创建bean

pring实现自动装配的方式: 通过组建扫描发现应用上下文所创建的bean并通过自动装配创建bean的依赖关系。

  1. 组件扫描 component-scan
  2. 自动装配 Autowire

在当今社会中,交通工具有多种多样,比如公交车、火车、飞机等。人们可以乘坐不同的司机驾驶的不同交通工具来出行。为了演示spring的实例,我们先建立Car接口:

/**
 * author yalunwang
 * 车抽象接口
 */
public interface Car {
    void notice();
}

其中notice方法代表车到站提醒。这样任意的交通工具都可实现接口Car,代码降低耦合。 这里我们先定义一个BusCar(公交车):

/**
 * author yalunwang
 * 公交车
 */
@Component
public class BusCar implements Car {
    private String carName="浦东25";

    @Override
    public void notice() {
        System.out.println(this.carName+"南京西路到了");
    }
}

@Component注解会告诉spring此类需要spring 创建该bean注册到 ioc容器中。因为组件扫描默认是不开启的,所以我们需要开启扫描,这样spring才会去寻找带有@Component的类并创建该bean。spring创建bean的时候都会给定一个ID,BusCar类的ID默认为busCar,会把类名的第一个变为小写。如果想指定ID为bus的可以这样写:@Component(value = “bus”)或@Component(“bus”)。]

告知spring开启自动扫描有两种办法:

  1. 在xml里配置
  2. 在javaconfig里配置

首先来看xml:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
       <context:component-scan base-package="com.yalunwang.autowiring"></context:component-scan>
</beans>

<context:component-scan>元素就是开启自动扫描,其中的base-package是告诉spring扫描com.yalunwang.autowiring包以及其下的所有子包中带有@Component注解的类,并为之创建。

我们再来看在java配置类里如何配置:

@Configuration
@ComponentScan(basePackages = "com.yalunwang.autowiring")
public class PeopleCarConfig {
}

@ComponentScan与xml中的 <context:component-scan>起到相同的作用。其中如果不加basePackages ,即表示以此配置类所在的包。

我们可以在单元测试里测试一下:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = PeopleCarConfig.class)
public class TestCar {
    @Autowired
    private BusCar busCar;
    @Test
    public void testCar()
    {
        System.out.println(busCar);
    }
}

结果输出: com.yalunwang.autowiring.BusCar@1c3d5104

  • @RunWith(SpringJUnit4ClassRunner.class) 会自动创建spring上下文
  • @ContextConfiguration 加载配置
  • @Autowired 注入同类型的实例

从结果中我们可以看出BusCar被spring创建。我们的自动扫描成功了。

自动装配

自动装配就是让spring自动将bean依赖的其他bean注入进去。我们可以使用@Autowired,在上文中的单元测试中我们刚刚使用了。为了演示自动装配我们再新建一个People接口用来抽象人类。

/**
 * author yalunwang
 * 人类抽象接口
 */
public interface People {
    void drive();
}

drive代表驾驶。 我们再创建一个Man来实现此接口。

/**
 * author yalunwang
 * 男人
 */
@Component
public class Man implements People {
    private String userName ="小明";

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    @Autowired
    private Car car;

    @Override

    public void drive() {
        //System.out.println("driver");
        System.out.println("男司机:" + this.userName);
        car.notice();
    }
}

drive:要想使车可以跑起来我们需要一个司机,司机驾驶车辆,并提醒乘客到达哪一站了。 所以我们的Man bean现在依赖于Car bean,这时我们再car字段添加注解@Autowired就会自动将Carbean注入进来。

这里注入的方式有很多种可以放到构造器,set方法,字段、其他方法。

    @Autowired
    private Car car;

    
    private Car car1;
    //构造器注入
    @Autowired
    public Man(Car car) {
        this.car1=car;
    }


    private Car car2;

    public Car getCar2() {
        return car2;
    }
    //set方法注入
    @Autowired
    public void setCar2(Car car2) {
        this.car2 = car2;
    }

下面我来验证一下

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = PeopleCarConfig.class)
public class TestPeople {
    @Autowired
    private People people;
    @Test
    public void test() {
        people.drive();
    }

}

输出:

男司机:小明
浦东25路南京西路到了

这里可以看出我们的自动装配是通过了。自动扫描配置Bean先告一段落。

Java代码中配置

javaconfig类需要添加@@Configuration 注解,要在显示的配置bean我们需要使用@Bean注解

@Configuration
public class PeopleCarConfig {
  
    @Bean
    public Car busCar()
    {
        return new  BusCar();
    }
}

@Bean注解会告诉spring这个方法将返回一个一个对象,并且要注册到spring上下文中。方法体力包含了最终产生bean实例的逻辑。Bean的ID默认是方法的名字,可以通过 @Bean(name=”busCar”)指定自定义的名字。

装配

我们知道人需要开车,Man依赖Car,那么我们如何将car注入到man中呢。

@Bean(name="man")
public People man()
{
    return new Man( busCar());
}

这样通过使用一个Car类型的实例对象BusCar的构造器构建Man实例,这里需要注意的是busCar()并非实际的方法调用,因为这个方法上加了@Bean注解,spring会拦截对他的调用并直接返回该方法所创建的bean。 我们可以做个实验:

@Configuration
public class PeopleCarConfig {
    private int i=1;
    @Bean
    public Car busCar()
    {
        i=i+1;
        System.out.println(i);
        return new  BusCar();
    }
    @Bean(name="man")
    public People man()
    {
        return new Man( busCar());
    }
    @Bean(name="woman")
    public People woman()
    {
        return new Woman( busCar());
    }
}

输出:

2
buscar构造函数
男司机:小明
浦东25路南京西路到了
女司机:小红
浦东25路南京西路到了

从这里就可以看出来 busCar()并不会真正的调用,而是直接返回spring创建的bean. 我们也可以通过另外一种方法来注入:

我们再创建一个Woman

public class Woman implements People {
    private Car car;
    public Woman(Car car){
        this.car=car;
    }
    private String userName ="小红";
    @Override
    public void drive() {
        System.out.println("女司机:" + this.userName);
        car.notice();
    }
}
  public People woman(Car car)
    {
        return new Woman( car);
    }

这里woman()方法加了一个Car参数,这里会自动装配一个Car类型的实现类实例。需要注意的是这里Car类型的bean可以通过xml 自动配置 javaconfig配置来进行配置。所以这种方式是最佳的注入方式。 以上我们使用的构造器的方式,其实我们也可以通过set方式等其他任意java方式去创建。

xml配置

在javaconfig中配置bean需要加@Configuration,xml配置对应的需要创建一个spring的xml规范文件。取名spring-test.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

</beans>

我们来配置一个bean

 <bean class="com.yalunwang.xmlconfig.BusCar" />

这个<bean> 配置相当于javaconfig中的@Bean,这时bean的id默认为完全限定名com.yalunwang.xmlconfig.BusCar#0 我们可以指定id: busCar

<bean id="busCar" class="com.yalunwang.xmlconfig.BusCar" />

这时spring创建busCar 的时候回自动调用busCar的默认构造函数。

下面我们来看在xml如何里装配

装配bean

  1. 构造器方式
<bean id="man" class="com.yalunwang.xmlconfig.Man" >
     <constructor-arg ref="busCar"/>
</bean>

这样就会在创建man实例的时候调用有参构造器,将id为busCar的bean实例注入进去。 我们也可以注入非引用类型即字面值:

 <bean id="busCar" class="com.yalunwang.xmlconfig.BusCar" >
              <constructor-arg name="carName" value="浦东2"></constructor-arg>
</bean>

xml还支持多种类型的注入,例如list.大家都知道公交车有很多的站点所以我们新增一个字段stationList用来存放站点列表。 我们也可以注入list类型

 <bean id="busCar" class="com.yalunwang.xmlconfig.BusCar" >
        <constructor-arg name="carName" value="浦东2"></constructor-arg>
         <constructor-arg name="stationList">
                 <list>
                        <value>高科中路</value>
                        <value>宜山路</value>
                        <value>桂林路</value>
                 </list>
            </constructor-arg>
 </bean>

同样的我们也可以使用<set> <map> <array>等来装配。

我们编写测试类来测试一下:


@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:spring-test.xml"})
public class Test {
    @Autowired
    private Car car;
    @org.junit.Test
    public void testBusCar()
    {
        car.notice();
        car.printStationList();
    }
     @Autowired
    private People people;
    @org.junit.Test
    public void testPeople()
    {
        people.drive();
    }
}

两个方法的输出分别是

浦东2路南京西路到了
站名:高科中路
站名:宜山路
站名:桂林路
男司机:小明
浦东2路南京西路到了

下面来看属性注入

  1. 属性注入

属注入是<property>元素

为了演示属性注入我们先把man注释掉,以避免我们再单元测试类中使用@AutoWired注解报错(因为有两个People的实例bean,后面文章会介绍这个问题)

 <!--<bean id="man" class="com.yalunwang.xmlconfig.Man" >-->
              <!--<constructor-arg name="car" ref="busCar"/>-->
       <!--</bean>-->
       <bean id="woman" class="com.yalunwang.xmlconfig.Woman" >
              <property name="car" ref="busCar"></property>
       </bean>

它会引用id为busCar的bean通过setCar()方法注入到car属性中。

这时我们在运行testPeople输出

女司机:小红
浦东2路南京西路到了

同样的属性也像构造函数方式注入一样可以注入字面值 <list><set>等类型的值。

 <bean id="woman" class="com.yalunwang.xmlconfig.Woman" >
             <property name="car" ref="busCar"></property>
             <property name="userName" value="韩梅梅"></property>
             <property name="certificateList" >
                    <list>
                           <value>驾驶证</value>
                           <value>身份证</value>
                    </list>
             </property>
      </bean>

我们再次测试:

女司机:韩梅梅
浦东2路南京西路到了
证书:驾驶证
证书:身份证

总结

以上就是spring中的三种装配Bean的方式,这里只是将最核心也是最基本的内容展示出来了,关于spring中更高级的装配我们将在后面文章讲解。

博客中的源码地址

github地址:https://github.com/yalunwang/java-clump

版权声明:本文为yalunwang原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:http://www.cnblogs.com/yalunwang/p/8065307.html