3.spring-2.0-ioc

资料:https://gitee.com/chuanqi1995/java

配置

pom.xml

<?xml version="1.0" encoding="UTF-8"?>

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>java-spring</artifactId>
        <groupId>org.example</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>

    <modelVersion>4.0.0</modelVersion>
    <artifactId>java-spring-1.0</artifactId>
    <packaging>war</packaging>

    <properties>
        <!-- dependency versions -->
        <servlet.api.version>2.4</servlet.api.version>
    </properties>


    <dependencies>
        <!-- requied start -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>servlet-api</artifactId>
            <version>${servlet.api.version}</version>
            <scope>provided</scope>
        </dependency>
        <!-- requied end -->
    </dependencies>

    <build>
        <finalName>${artifactId}</finalName>
        <resources>
            <resource>
                <directory>${basedir}/src/main/resources</directory>
                <includes>
                    <include>**/*</include>
                </includes>
            </resource>
            <resource>
                <directory>${basedir}/src/main/java</directory>
                <excludes>
                    <exclude>**/*.java</exclude>
                    <exclude>**/*.class</exclude>
                </excludes>
            </resource>
        </resources>
        <plugins>
            <plugin>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>2.3.2</version>
                <configuration>
                    <source>1.6</source>
                    <target>1.6</target>
                    <encoding>UTF-8</encoding>
                    <compilerArguments>
                        <verbose/>
                        <bootclasspath>${java.home}/lib/rt.jar</bootclasspath>
                    </compilerArguments>
                </configuration>
            </plugin>

            <plugin>
                <artifactId>maven-resources-plugin</artifactId>
                <version>2.5</version>
                <executions>
                    <execution>
                        <id>copy-resources</id>
                        <!-- here the phase you need -->
                        <phase>validate</phase>
                        <goals>
                            <goal>copy-resources</goal>
                        </goals>
                        <configuration>
                            <encoding>UTF-8</encoding>
                            <outputDirectory>${basedir}/target/classes</outputDirectory>
                            <resources>
                                <resource>
                                    <directory>src/main/resources</directory>
                                    <includes>
                                        <include>**/*.*</include>
                                    </includes>
                                    <filtering>true</filtering>
                                </resource>
                            </resources>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <groupId>org.mortbay.jetty</groupId>
                <artifactId>maven-jetty-plugin</artifactId>
                <version>6.1.26</version>
                <configuration>
                    <webDefaultXml>src/main/resources/webdefault.xml</webDefaultXml>
                    <contextPath>/</contextPath>
                    <connectors>
                        <connector implementation="org.mortbay.jetty.nio.SelectChannelConnector">
                            <port>8080</port>
                        </connector>
                    </connectors>
                    <scanIntervalSeconds>0</scanIntervalSeconds>
                    <scanTargetPatterns>
                        <scanTargetPattern>
                            <directory>src/main/webapp</directory>
                            <includes>
                                <include>**/*.xml</include>
                                <include>**/*.properties</include>
                            </includes>
                        </scanTargetPattern>
                    </scanTargetPatterns>
                    <systemProperties>
                        <systemProperty>
                            <name>
                                javax.xml.parsers.DocumentBuilderFactory
                            </name>
                            <value>
                                com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl
                            </value>
                        </systemProperty>
                        <systemProperty>
                            <name>
                                javax.xml.parsers.SAXParserFactory
                            </name>
                            <value>
                                com.sun.org.apache.xerces.internal.jaxp.SAXParserFactoryImpl
                            </value>
                        </systemProperty>
                        <systemProperty>
                            <name>
                                javax.xml.transform.TransformerFactory
                            </name>
                            <value>
                                com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl
                            </value>
                        </systemProperty>
                        <systemProperty>
                            <name>org.eclipse.jetty.util.URI.charset</name>
                            <value>UTF-8</value>
                        </systemProperty>
                    </systemProperties>
                </configuration>
            </plugin>

            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-war-plugin</artifactId>
                <version>2.2</version>
                <configuration>
                    <archive>
                        <addMavenDescriptor>false</addMavenDescriptor>
                    </archive>
                    <webResources>
                        <resource>
                            <!-- this is relative to the pom.xml directory -->
                            <directory>src/main/resources/</directory>
                            <targetPath>WEB-INF/classes</targetPath>
                            <includes>
                                <include>**/*.*</include>
                            </includes>
                            <!-- <excludes>
                                <exclude>**/local</exclude>
                                <exclude>**/test</exclude>
                                <exclude>**/product</exclude>
                            </excludes> -->
                            <filtering>true</filtering>
                        </resource>
                        <resource>
                            <!-- this is relative to the pom.xml directory -->
                            <directory>src/main/resources</directory>
                            <targetPath>WEB-INF/classes</targetPath>
                            <filtering>true</filtering>
                        </resource>
                    </webResources>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.zeroturnaround</groupId>
                <artifactId>javarebel-maven-plugin</artifactId>
                <executions>
                    <execution>
                        <id>generate-rebel-xml</id>
                        <phase>process-resources</phase>
                        <goals>
                            <goal>generate</goal>
                        </goals>
                    </execution>
                </executions>
                <version>1.0.5</version>
            </plugin>

        </plugins>
        <pluginManagement>
            <plugins>
                <!--This plugin's configuration is used to store Eclipse m2e settings
                    only. It has no influence on the Maven build itself. -->
                <plugin>
                    <groupId>org.eclipse.m2e</groupId>
                    <artifactId>lifecycle-mapping</artifactId>
                    <version>1.0.0</version>
                    <configuration>
                        <lifecycleMappingMetadata>
                            <pluginExecutions>
                                <pluginExecution>
                                    <pluginExecutionFilter>
                                        <groupId>
                                            org.zeroturnaround
                                        </groupId>
                                        <artifactId>
                                            javarebel-maven-plugin
                                        </artifactId>
                                        <versionRange>
                                            [1.0.5,)
                                        </versionRange>
                                        <goals>
                                            <goal>generate</goal>
                                        </goals>
                                    </pluginExecutionFilter>
                                    <action>
                                        <ignore></ignore>
                                    </action>
                                </pluginExecution>
                            </pluginExecutions>
                        </lifecycleMappingMetadata>
                    </configuration>
                </plugin>
            </plugins>
        </pluginManagement>
    </build>
</project>

webdefault.xml

<?xml version="1.0" encoding="ISO-8859-1"?>

<!-- ===================================================================== -->
<!-- This file contains the default descriptor for web applications.       -->
<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
<!-- The intent of this descriptor is to include jetty specific or common  -->
<!-- configuration for all webapps.   If a context has a webdefault.xml    -->
<!-- descriptor, it is applied before the contexts own web.xml file        -->
<!--                                                                       -->
<!-- A context may be assigned a default descriptor by:                    -->
<!--  + Calling WebApplicationContext.setDefaultsDescriptor                -->
<!--  + Passed an arg to addWebApplications                                -->
<!--                                                                       -->
<!-- This file is used both as the resource within the jetty.jar (which is -->
<!-- used as the default if no explicit defaults descriptor is set) and it -->
<!-- is copied to the etc directory of the Jetty distro and explicitly     -->
<!-- by the jetty.xml file.                                                -->
<!--                                                                       -->
<!-- ===================================================================== -->
<web-app 
   xmlns="http://java.sun.com/xml/ns/javaee" 
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" 
   metadata-complete="true"
   version="2.5"> 

  <description>
    Default web.xml file.  
    This file is applied to a Web application before it's own WEB_INF/web.xml file
  </description>


  <!-- ==================================================================== -->
  <!-- Context params to control Session Cookies                            -->
  <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  -->
  <!-- UNCOMMENT TO ACTIVATE
  <context-param>
    <param-name>org.mortbay.jetty.servlet.SessionDomain</param-name>
    <param-value>127.0.0.1</param-value>
  </context-param>

  <context-param>
    <param-name>org.mortbay.jetty.servlet.SessionPath</param-name>
    <param-value>/</param-value>
  </context-param>

  <context-param>
    <param-name>org.mortbay.jetty.servlet.MaxAge</param-name>
    <param-value>-1</param-value>
  </context-param>
  -->

  <context-param>
    <param-name>org.mortbay.jetty.webapp.NoTLDJarPattern</param-name>
    <param-value>start.jar|ant-.*\.jar|dojo-.*\.jar|jetty-.*\.jar|jsp-api-.*\.jar|junit-.*\.jar|servlet-api-.*\.jar|dnsns\.jar|rt\.jar|jsse\.jar|tools\.jar|sunpkcs11\.jar|sunjce_provider\.jar|xerces.*\.jar</param-value>
  </context-param>
            


  <!-- ==================================================================== -->
  <!-- The default servlet.                                                 -->
  <!-- This servlet, normally mapped to /, provides the handling for static -->
  <!-- content, OPTIONS and TRACE methods for the context.                  -->
  <!-- The following initParameters are supported:                          -->
  <!--                                                                      -->
  <!--   acceptRanges     If true, range requests and responses are         -->
  <!--                    supported                                         -->
  <!--                                                                      -->
  <!--   dirAllowed       If true, directory listings are returned if no    -->
  <!--                    welcome file is found. Else 403 Forbidden.        -->
  <!--                                                                      -->
  <!--   welcomeServlets  If true, attempt to dispatch to welcome files     -->
  <!--                    that are servlets, if no matching static          --> 
  <!--                    resources can be found.                           -->
  <!--                                                                      -->
  <!--   redirectWelcome  If true, redirect welcome file requests           -->
  <!--                    else use request dispatcher forwards              -->
  <!--                                                                      -->
  <!--   gzip             If set to true, then static content will be served--> 
  <!--                    as gzip content encoded if a matching resource is -->
  <!--                    found ending with ".gz"                           -->
  <!--                                                                      -->
  <!--   resoureBase      Can be set to replace the context resource base   -->
  <!--                                                                      -->
  <!--   relativeResourceBase                                               -->
  <!--                    Set with a pathname relative to the base of the   -->
  <!--                    servlet context root. Useful for only serving     -->
  <!--                    static content from only specific subdirectories. -->
  <!--                                                                      -->
  <!--   useFileMappedBuffer                                                -->
  <!--                    If set to true (the default), a  memory mapped    -->
  <!--                    file buffer will be used to serve static content  -->
  <!--                    when using an NIO connector. Setting this value   -->
  <!--                    to false means that a direct buffer will be used  -->
  <!--                    instead. If you are having trouble with Windows   -->
  <!--                    file locking, set this to false.                  -->
  <!--                                                                      -->
  <!--  cacheControl      If set, all static content will have this value   -->
  <!--                    set as the cache-control header.                  -->
  <!--                                                                      -->
  <!--  maxCacheSize      Maximum size of the static resource cache         -->
  <!--                                                                      -->
  <!--  maxCachedFileSize Maximum size of any single file in the cache      -->
  <!--                                                                      -->
  <!--  maxCachedFiles    Maximum number of files in the cache              -->
  <!--                                                                      -->
  <!--  cacheType         "nio", "bio" or "both" to determine the type(s)   -->
  <!--                    of resource cache. A bio cached buffer may be used-->
  <!--                    by nio but is not as efficient as a nio buffer.   -->
  <!--                    An nio cached buffer may not be used by bio.      -->
  <!--                                                                      -->
  <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  -->
  <servlet>
    <servlet-name>default</servlet-name>
    <servlet-class>org.mortbay.jetty.servlet.DefaultServlet</servlet-class>
    <init-param>
      <param-name>acceptRanges</param-name>
      <param-value>true</param-value>
    </init-param>
    <init-param>
      <param-name>dirAllowed</param-name>
      <param-value>true</param-value>
    </init-param>
    <init-param>
      <param-name>welcomeServlets</param-name>
      <param-value>false</param-value>
    </init-param>
    <init-param>
      <param-name>redirectWelcome</param-name>
      <param-value>false</param-value>
    </init-param>
    <init-param>
      <param-name>maxCacheSize</param-name>
      <param-value>256000000</param-value>
    </init-param>
    <init-param>
      <param-name>maxCachedFileSize</param-name>
      <param-value>10000000</param-value>
    </init-param>
    <init-param>
      <param-name>maxCachedFiles</param-name>
      <param-value>1000</param-value>
    </init-param>
    <init-param>
      <param-name>cacheType</param-name>
      <param-value>both</param-value>
    </init-param>
    <init-param>
      <param-name>gzip</param-name>
      <param-value>true</param-value>
    </init-param>
    <init-param>
      <param-name>useFileMappedBuffer</param-name>
      <param-value>false</param-value>
    </init-param>  
    <!--
    <init-param>
      <param-name>cacheControl</param-name>
      <param-value>max-age=3600,public</param-value>
    </init-param>
    -->
    <load-on-startup>0</load-on-startup>
  </servlet> 

  <servlet-mapping> <servlet-name>default</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping>
  

  <!-- ==================================================================== -->
  <!-- JSP Servlet                                                          -->
  <!-- This is the jasper JSP servlet from the jakarta project              -->
  <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  -->
  <!-- The JSP page compiler and execution servlet, which is the mechanism  -->
  <!-- used by Glassfish to support JSP pages.  Traditionally, this servlet -->
  <!-- is mapped to URL patterh "*.jsp".  This servlet supports the         -->
  <!-- following initialization parameters (default values are in square    -->
  <!-- brackets):                                                           -->
  <!--                                                                      -->
  <!--   checkInterval       If development is false and reloading is true, -->
  <!--                       background compiles are enabled. checkInterval -->
  <!--                       is the time in seconds between checks to see   -->
  <!--                       if a JSP page needs to be recompiled. [300]    -->
  <!--                                                                      -->
  <!--   compiler            Which compiler Ant should use to compile JSP   -->
  <!--                       pages.  See the Ant documenation for more      -->
  <!--                       information. [javac]                           -->
  <!--                                                                      -->
  <!--   classdebuginfo      Should the class file be compiled with         -->
  <!--                       debugging information?  [true]                 -->
  <!--                                                                      -->
  <!--   classpath           What class path should I use while compiling   -->
  <!--                       generated servlets?  [Created dynamically      -->
  <!--                       based on the current web application]          -->
  <!--                       Set to ? to make the container explicitly set  -->
  <!--                       this parameter.                                -->
  <!--                                                                      -->
  <!--   development         Is Jasper used in development mode (will check -->
  <!--                       for JSP modification on every access)?  [true] -->
  <!--                                                                      -->
  <!--   enablePooling       Determines whether tag handler pooling is      -->
  <!--                       enabled  [true]                                -->
  <!--                                                                      -->
  <!--   fork                Tell Ant to fork compiles of JSP pages so that -->
  <!--                       a separate JVM is used for JSP page compiles   -->
  <!--                       from the one Tomcat is running in. [true]      -->
  <!--                                                                      -->
  <!--   ieClassId           The class-id value to be sent to Internet      -->
  <!--                       Explorer when using <jsp:plugin> tags.         -->
  <!--                       [clsid:8AD9C840-044E-11D1-B3E9-00805F499D93]   -->
  <!--                                                                      -->
  <!--   javaEncoding        Java file encoding to use for generating java  -->
  <!--                       source files. [UTF-8]                          -->
  <!--                                                                      -->
  <!--   keepgenerated       Should we keep the generated Java source code  -->
  <!--                       for each page instead of deleting it? [true]   -->
  <!--                                                                      -->
  <!--   logVerbosityLevel   The level of detailed messages to be produced  -->
  <!--                       by this servlet.  Increasing levels cause the  -->
  <!--                       generation of more messages.  Valid values are -->
  <!--                       FATAL, ERROR, WARNING, INFORMATION, and DEBUG. -->
  <!--                       [WARNING]                                      -->
  <!--                                                                      -->
  <!--   mappedfile          Should we generate static content with one     -->
  <!--                       print statement per input line, to ease        -->
  <!--                       debugging?  [false]                            -->
  <!--                                                                      -->
  <!--                                                                      -->
  <!--   reloading           Should Jasper check for modified JSPs?  [true] -->
  <!--                                                                      -->
  <!--   suppressSmap        Should the generation of SMAP info for JSR45   -->
  <!--                       debugging be suppressed?  [false]              -->
  <!--                                                                      -->
  <!--   dumpSmap            Should the SMAP info for JSR45 debugging be    -->
  <!--                       dumped to a file? [false]                      -->
  <!--                       False if suppressSmap is true                  -->
  <!--                                                                      -->
  <!--   scratchdir          What scratch directory should we use when      -->
  <!--                       compiling JSP pages?  [default work directory  -->
  <!--                       for the current web application]               -->
  <!--                                                                      -->
  <!--   tagpoolMaxSize      The maximum tag handler pool size  [5]         -->
  <!--                                                                      -->
  <!--   xpoweredBy          Determines whether X-Powered-By response       -->
  <!--                       header is added by generated servlet  [false]  -->
  <!--                                                                      -->
  <!-- If you wish to use Jikes to compile JSP pages:                       -->
  <!--   Set the init parameter "compiler" to "jikes".  Define              -->
  <!--   the property "-Dbuild.compiler.emacs=true" when starting Jetty     -->
  <!--   to cause Jikes to emit error messages in a format compatible with  -->
  <!--   Jasper.                                                            -->
  <!--   If you get an error reporting that jikes can't use UTF-8 encoding, -->
  <!--   try setting the init parameter "javaEncoding" to "ISO-8859-1".     -->
  <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  -->
  <servlet id="jsp">
    <servlet-name>jsp</servlet-name>
    <servlet-class>org.apache.jasper.servlet.JspServlet</servlet-class>
    <init-param>
        <param-name>logVerbosityLevel</param-name>
        <param-value>DEBUG</param-value>
    </init-param>
    <init-param>
        <param-name>fork</param-name>
        <param-value>false</param-value>
    </init-param>
    <init-param>
        <param-name>xpoweredBy</param-name>
        <param-value>false</param-value>
    </init-param>
    <!--  
    <init-param>
        <param-name>classpath</param-name>
        <param-value>?</param-value>
    </init-param>
    -->
    <load-on-startup>0</load-on-startup>
  </servlet>

  <servlet-mapping> 
    <servlet-name>jsp</servlet-name> 
    <url-pattern>*.jsp</url-pattern> 
    <url-pattern>*.jspf</url-pattern>
    <url-pattern>*.jspx</url-pattern>
    <url-pattern>*.xsp</url-pattern>
    <url-pattern>*.JSP</url-pattern> 
    <url-pattern>*.JSPF</url-pattern>
    <url-pattern>*.JSPX</url-pattern>
    <url-pattern>*.XSP</url-pattern>
  </servlet-mapping>
  
  <!-- ==================================================================== -->
  <!-- Dynamic Servlet Invoker.                                             -->
  <!-- This servlet invokes anonymous servlets that have not been defined   -->
  <!-- in the web.xml or by other means. The first element of the pathInfo  -->
  <!-- of a request passed to the envoker is treated as a servlet name for  -->
  <!-- an existing servlet, or as a class name of a new servlet.            -->
  <!-- This servlet is normally mapped to /servlet/*                        -->
  <!-- This servlet support the following initParams:                       -->
  <!--                                                                      -->
  <!--  nonContextServlets       If false, the invoker can only load        -->
  <!--                           servlets from the contexts classloader.    -->
  <!--                           This is false by default and setting this  -->
  <!--                           to true may have security implications.    -->
  <!--                                                                      -->
  <!--  verbose                  If true, log dynamic loads                 -->
  <!--                                                                      -->
  <!--  *                        All other parameters are copied to the     -->
  <!--                           each dynamic servlet as init parameters    -->
  <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  -->
  <!-- Uncomment for dynamic invocation
  <servlet>
    <servlet-name>invoker</servlet-name>
    <servlet-class>org.mortbay.jetty.servlet.Invoker</servlet-class>
    <init-param>
      <param-name>verbose</param-name>
      <param-value>false</param-value>
    </init-param>
    <init-param>
      <param-name>nonContextServlets</param-name>
      <param-value>false</param-value>
    </init-param>
    <init-param>
      <param-name>dynamicParam</param-name>
      <param-value>anyValue</param-value>
    </init-param>
    <load-on-startup>0</load-on-startup>
  </servlet>

  <servlet-mapping> <servlet-name>invoker</servlet-name> <url-pattern>/servlet/*</url-pattern> </servlet-mapping>
  -->



  <!-- ==================================================================== -->
  <session-config>
    <session-timeout>30</session-timeout>
  </session-config>

  <!-- ==================================================================== -->
  <!-- Default MIME mappings                                                -->
  <!-- The default MIME mappings are provided by the mime.properties        -->
  <!-- resource in the org.mortbay.jetty.jar file.  Additional or modified  -->
  <!-- mappings may be specified here                                       -->
  <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  -->
  <!-- UNCOMMENT TO ACTIVATE
  <mime-mapping>
    <extension>mysuffix</extension>
    <mime-type>mymime/type</mime-type>
  </mime-mapping>
  -->

  <!-- ==================================================================== -->
  <welcome-file-list>
    <welcome-file>index.html</welcome-file>
    <welcome-file>index.htm</welcome-file>
    <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>

  <!-- ==================================================================== -->
  <locale-encoding-mapping-list>
    <locale-encoding-mapping><locale>ar</locale><encoding>ISO-8859-6</encoding></locale-encoding-mapping>
    <locale-encoding-mapping><locale>be</locale><encoding>ISO-8859-5</encoding></locale-encoding-mapping>
    <locale-encoding-mapping><locale>bg</locale><encoding>ISO-8859-5</encoding></locale-encoding-mapping>
    <locale-encoding-mapping><locale>ca</locale><encoding>ISO-8859-1</encoding></locale-encoding-mapping>
    <locale-encoding-mapping><locale>cs</locale><encoding>ISO-8859-2</encoding></locale-encoding-mapping>
    <locale-encoding-mapping><locale>da</locale><encoding>ISO-8859-1</encoding></locale-encoding-mapping>
    <locale-encoding-mapping><locale>de</locale><encoding>ISO-8859-1</encoding></locale-encoding-mapping>
    <locale-encoding-mapping><locale>el</locale><encoding>ISO-8859-7</encoding></locale-encoding-mapping>
    <locale-encoding-mapping><locale>en</locale><encoding>ISO-8859-1</encoding></locale-encoding-mapping>
    <locale-encoding-mapping><locale>es</locale><encoding>ISO-8859-1</encoding></locale-encoding-mapping>
    <locale-encoding-mapping><locale>et</locale><encoding>ISO-8859-1</encoding></locale-encoding-mapping>
    <locale-encoding-mapping><locale>fi</locale><encoding>ISO-8859-1</encoding></locale-encoding-mapping>
    <locale-encoding-mapping><locale>fr</locale><encoding>ISO-8859-1</encoding></locale-encoding-mapping>
    <locale-encoding-mapping><locale>hr</locale><encoding>ISO-8859-2</encoding></locale-encoding-mapping>
    <locale-encoding-mapping><locale>hu</locale><encoding>ISO-8859-2</encoding></locale-encoding-mapping>
    <locale-encoding-mapping><locale>is</locale><encoding>ISO-8859-1</encoding></locale-encoding-mapping>
    <locale-encoding-mapping><locale>it</locale><encoding>ISO-8859-1</encoding></locale-encoding-mapping>
    <locale-encoding-mapping><locale>iw</locale><encoding>ISO-8859-8</encoding></locale-encoding-mapping>
    <locale-encoding-mapping><locale>ja</locale><encoding>Shift_JIS</encoding></locale-encoding-mapping>
    <locale-encoding-mapping><locale>ko</locale><encoding>EUC-KR</encoding></locale-encoding-mapping>     
    <locale-encoding-mapping><locale>lt</locale><encoding>ISO-8859-2</encoding></locale-encoding-mapping>
    <locale-encoding-mapping><locale>lv</locale><encoding>ISO-8859-2</encoding></locale-encoding-mapping>
    <locale-encoding-mapping><locale>mk</locale><encoding>ISO-8859-5</encoding></locale-encoding-mapping>
    <locale-encoding-mapping><locale>nl</locale><encoding>ISO-8859-1</encoding></locale-encoding-mapping>
    <locale-encoding-mapping><locale>no</locale><encoding>ISO-8859-1</encoding></locale-encoding-mapping>
    <locale-encoding-mapping><locale>pl</locale><encoding>ISO-8859-2</encoding></locale-encoding-mapping>
    <locale-encoding-mapping><locale>pt</locale><encoding>ISO-8859-1</encoding></locale-encoding-mapping>
    <locale-encoding-mapping><locale>ro</locale><encoding>ISO-8859-2</encoding></locale-encoding-mapping>
    <locale-encoding-mapping><locale>ru</locale><encoding>ISO-8859-5</encoding></locale-encoding-mapping>
    <locale-encoding-mapping><locale>sh</locale><encoding>ISO-8859-5</encoding></locale-encoding-mapping>
    <locale-encoding-mapping><locale>sk</locale><encoding>ISO-8859-2</encoding></locale-encoding-mapping>
    <locale-encoding-mapping><locale>sl</locale><encoding>ISO-8859-2</encoding></locale-encoding-mapping>
    <locale-encoding-mapping><locale>sq</locale><encoding>ISO-8859-2</encoding></locale-encoding-mapping>
    <locale-encoding-mapping><locale>sr</locale><encoding>ISO-8859-5</encoding></locale-encoding-mapping>
    <locale-encoding-mapping><locale>sv</locale><encoding>ISO-8859-1</encoding></locale-encoding-mapping>
    <locale-encoding-mapping><locale>tr</locale><encoding>ISO-8859-9</encoding></locale-encoding-mapping>
    <locale-encoding-mapping><locale>uk</locale><encoding>ISO-8859-5</encoding></locale-encoding-mapping>
    <locale-encoding-mapping><locale>zh</locale><encoding>GB2312</encoding></locale-encoding-mapping>
    <locale-encoding-mapping><locale>zh_TW</locale><encoding>Big5</encoding></locale-encoding-mapping>   
  </locale-encoding-mapping-list>
  
  <security-constraint>
    <web-resource-collection>
      <web-resource-name>Disable TRACE</web-resource-name>
      <url-pattern>/</url-pattern>
      <http-method>TRACE</http-method>
    </web-resource-collection>
    <auth-constraint/>
  </security-constraint>
  
</web-app>

application.properties

scanPackage=com.demo.spring.ioc.v2

web.xml

<!DOCTYPE web-app PUBLIC
        "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
        "http://java.sun.com/dtd/web-app_2_3.dtd" >

<web-app>
    <display-name>Archetype Created Web Application</display-name>
    <servlet>
        <servlet-name>sucqmvc</servlet-name>
        <servlet-class>com.mvcframework.v2.servlet.SDispatchServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>application.properties</param-value>
        </init-param>

        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>sucqmvc</servlet-name>
        <url-pattern>/*</url-pattern>
    </servlet-mapping>
</web-app>

业务代码

controller

package com.demo.spring.action;

import com.demo.spring.service.IDemoService;
import com.mvcframework.annotation.SAutowired;
import com.mvcframework.annotation.SController;
import com.mvcframework.annotation.SRequestMapping;
import com.mvcframework.annotation.SRequestParam;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;


//虽然,用法一样,但是没有功能
@SController
@SRequestMapping("/demo")
public class DemoAction {

   @SAutowired
   private IDemoService demoService;

   @SRequestMapping("/query")
   public void query(HttpServletRequest req, HttpServletResponse resp,
                 @SRequestParam("name") String name){
      String result = demoService.get(name);
//    String result = "My name is " + name;
      try {
         resp.getWriter().write(result);
      } catch (IOException e) {
         e.printStackTrace();
      }
   }

   @SRequestMapping("/add")
   public void add(HttpServletRequest req, HttpServletResponse resp,
               @SRequestParam("a") Integer a, @SRequestParam("b") Integer b){
      try {
         resp.getWriter().write(a + "+" + b + "=" + (a + b));
      } catch (IOException e) {
         e.printStackTrace();
      }
   }

   @SRequestMapping("/sub")
   public void add(HttpServletRequest req, HttpServletResponse resp,
               @SRequestParam("a") Double a, @SRequestParam("b") Double b){
      try {
         resp.getWriter().write(a + "-" + b + "=" + (a - b));
      } catch (IOException e) {
         e.printStackTrace();
      }
   }

   @SRequestMapping("/remove")
   public String  remove(@SRequestParam("id") Integer id){
      return "" + id;
   }


}
package com.demo.spring.action;


//没加注解,控制权不反转,自己管自己
public class TestAction {
}
package com.demo.spring.action;

import com.demo.spring.service.IDemoService;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

//没加注解,控制权不反转,自己管自己
public class TwoAction {
   
   private IDemoService demoService;

   public void edit(HttpServletRequest req,HttpServletResponse resp,
                String name){
      String result = demoService.get(name);
      try {
         resp.getWriter().write(result);
      } catch (IOException e) {
         e.printStackTrace();
      }
   }
   
}

entity

package com.demo.spring.entity;

public class Test {

    public static void main(String[] args) {
        String simpleName = Test.class.getSimpleName();
        System.out.println(simpleName);
    }
}

service

package com.demo.spring.service;


public interface IDemoService {
   
   String get(String name);
   
}
package com.demo.spring.service.impl;

import com.demo.spring.service.IDemoService;
import com.mvcframework.annotation.SService;

/**
 * 核心业务逻辑
 */
@SService
public class DemoService implements IDemoService {

   public String get(String name) {
      return "My name is " + name + ",from service.";
   }

}

spring代码

注解

package com.mvcframework.annotation;

import java.lang.annotation.*;

@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface SAutowired {
    String value() default "";
}
package com.mvcframework.annotation;

import java.lang.annotation.*;

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface SController {
    String value() default "";
}
package com.mvcframework.annotation;

import java.lang.annotation.*;

@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface SRequestMapping {
    String value() default "";
}
package com.mvcframework.annotation;

import java.lang.annotation.*;

@Target({ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface SRequestParam {
    String value() default "";
}
package com.mvcframework.annotation;

import java.lang.annotation.*;

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface SService {
    String value() default "";
}

servlet

package com.spring.framework.webmvc.servlet;

import com.spring.framework.annotation.*;
import com.spring.framework.context.SApplicationContext;
import com.spring.framework.support.SDefaultListableBeanFactory;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.net.URL;
import java.util.*;


public class SDispatchServlet extends HttpServlet {
    /**
     * Spring设计思路
     * 一、知识点
     * 1、Spring中的bean默认是单例的
     * 2、Spring中的bean默认是非延时加载的
     *      1、非延时加载:在Spring启动之后,对象就创建在Spring的IOC容器里了
     *      2、延时加载:在用户使用ApplicationContext.getBean()时才加载bean到IOC容器
     *
     * 二、步骤
     * 在调用Servlet的init方法的时候
     * 1、初始化AppliactionContext
     * 2、加载配置文件
     *      1、读取到配置文件(BeanDefinitionReader)
     *      2、扫描到相关的类,保存起来(BeanDefinitionReader)
     * 3、解析配置文件,将所有配置文件封装起来(BeanDefinition)
     * 4、将所有封装起来的BeanDefinition缓存起来(SDefaultListableBeanFactory)
     * 5、加载非延时加载的所有bean(getBean())
     *
     * 在调用ApplicationContext.getBean()方法时
     * 6、先根据beanName拿到BeanDefinition配置信息
     * 7、反射实例化对象
     * 8、将返回的bean封装成(BeanWrapper)
     * 9、DI依赖注入
     * 10、存入一级缓存
     */
    // ==================Spring-2.0-ioc开始==================
    SApplicationContext applicationContext;


    // ==================Spring-2.0-ioc结束==================
    private Map<String,Method> handlerMapping = new HashMap<String, Method>();

    @Override
    public void init(ServletConfig config) throws ServletException {
        // 1、初始化AppliactionContext
        applicationContext = new SApplicationContext(config.getInitParameter("contextConfigLocation").replaceAll("classpath:", ""));
        //==============MVC部分==============
        //2、初始化HandlerMapping
        doInitHandlerMapping();

        System.out.println("S Spring framework is init.");
    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        this.doPost(req,resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        //6、委派,根据URL去找到一个对应的Method并通过response返回
        try {
            doDispatch(req,resp);
        } catch (Exception e) {
            e.printStackTrace();
            resp.getWriter().write("500 Exception,Detail : " + Arrays.toString(e.getStackTrace()));
        }

    }

    private void doDispatch(HttpServletRequest req, HttpServletResponse resp) throws Exception {
        String url = req.getRequestURI();
        String contextPath = req.getContextPath();
        url = url.replaceAll(contextPath,"").replaceAll("/+","/");

        if(!this.handlerMapping.containsKey(url)){
            resp.getWriter().write("404 Not Found!!!");
            return;
        }

        Map<String,String[]> params = req.getParameterMap();

        Method method = this.handlerMapping.get(url);


        //获取形参列表
        Class<?> [] parameterTypes = method.getParameterTypes();
        Object [] paramValues = new Object[parameterTypes.length];

        for (int i = 0; i < parameterTypes.length; i++) {
            Class paramterType = parameterTypes[i];
            if(paramterType == HttpServletRequest.class){
                paramValues[i] = req;
            }else if(paramterType == HttpServletResponse.class){
                paramValues[i] = resp;
            }else if(paramterType == String.class){
                //通过运行时的状态去拿到你
                Annotation[] [] pa = method.getParameterAnnotations();
                for (int j = 0; j < pa.length ; j ++) {
                    for(Annotation a : pa[i]){
                        if(a instanceof SRequestParam){
                            String paramName = ((SRequestParam) a).value();
                            if(!"".equals(paramName.trim())){
                               String value = Arrays.toString(params.get(paramName))
                                       .replaceAll("\\[|\\]","")
                                       .replaceAll("\\s+",",");
                                paramValues[i] = value;
                            }
                        }
                    }
                }

            }
        }


        //暂时硬编码
        String beanName = toLowerFirstCase(method.getDeclaringClass().getSimpleName());
        //赋值实参列表
        method.invoke(applicationContext.getBean(beanName),paramValues);

    }

    private void doInitHandlerMapping() {
        if(this.applicationContext.getBeanDefinitionCount() == 0){
            return;
        }
        for (String beanName : this.applicationContext.getBeanDefinitionNames()) {
            Object instance = applicationContext.getBean(beanName);
            Class<?> clazz = instance.getClass();

            if(!clazz.isAnnotationPresent(SController.class)){ continue; }


            //相当于提取 class上配置的url
            String baseUrl = "";
            if(clazz.isAnnotationPresent(SRequestMapping.class)){
                SRequestMapping requestMapping = clazz.getAnnotation(SRequestMapping.class);
                baseUrl = requestMapping.value();
            }

            //只获取public的方法
            for (Method method : clazz.getMethods()) {
                if(!method.isAnnotationPresent(SRequestMapping.class)){continue;}
                //提取每个方法上面配置的url
                SRequestMapping requestMapping = method.getAnnotation(SRequestMapping.class);

                // //demo//query
                String url = ("/" + baseUrl + "/" + requestMapping.value()).replaceAll("/+","/");
                handlerMapping.put(url,method);
                System.out.println("Mapped : " + url + "," + method);
            }
        }
    }

    //自己写,自己用
    private String toLowerFirstCase(String simpleName) {
        char [] chars = simpleName.toCharArray();
//        if(chars[0] > )
        chars[0] += 32;
        return String.valueOf(chars);
    }

}

context

package com.spring.framework.context;

import com.spring.framework.annotation.SAutowired;
import com.spring.framework.annotation.SController;
import com.spring.framework.annotation.SService;
import com.spring.framework.beans.SBeanWrapper;
import com.spring.framework.beans.config.SBeanDefinition;
import com.spring.framework.core.SBeanFactory;
import com.spring.framework.support.SBeanDefinitionReader;
import com.spring.framework.support.SDefaultListableBeanFactory;

import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class SApplicationContext implements SBeanFactory {
    // 加载配置文件
    private SBeanDefinitionReader reader;
    private SDefaultListableBeanFactory registry = new SDefaultListableBeanFactory();
    private Map<String,Object> factoryBeanObjectCache = new HashMap<String, Object>();
    // 三级缓存(终极缓存)
    private Map<String, SBeanWrapper> factoryBeanInstanceCache = new HashMap<String, SBeanWrapper>();

    public SApplicationContext(String... configLocations) {
        // 2、加载配置文件
        reader = new SBeanDefinitionReader(configLocations);
        try {
            // 3、解析配置文件,将所有配置文件封装起来(BeanDefinition)
            List<SBeanDefinition> beanDefinitions = reader.loadBeanDefinitions();
            // 4、将所有封装起来的BeanDefinition缓存起来(SDefaultListableBeanFactory)
            this.registry.doRegistBeanDefinition(beanDefinitions);
            // 5、加载非延时加载的所有bean(getBean())
            doLoadInstance();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public Object getBean(String beanName) {
        // 6、先根据beanName拿到BeanDefinition配置信息
        SBeanDefinition beanDefinition = registry.beanDefinitionMap.get(beanName);
        // 7、反射实例化对象
        Object instance = initantiateBean(beanName, beanDefinition);
        // 8、将返回的bean封装成(BeanWrapper)
        SBeanWrapper beanWrapper = new SBeanWrapper(instance);
        // 9、DI依赖注入
        populateBean(beanName, beanDefinition, beanWrapper);
        // 10、保存到IOC容器中
        this.factoryBeanInstanceCache.put(beanName,beanWrapper);
        return beanWrapper.getWrapperedInstance();
    }

    private void populateBean(String beanName, SBeanDefinition beanDefinition, SBeanWrapper beanWrapper) {
        Object instance = beanWrapper.getWrapperedInstance();
        Class<?> clazz = beanWrapper.getWrapperClass();

        if(!(clazz.isAnnotationPresent(SController.class)
                || clazz.isAnnotationPresent(SService.class))){
            return;
        }

        //把所有的包括private/protected/default/public 修饰字段都取出来
        for (Field field : clazz.getDeclaredFields()) {
            if(!field.isAnnotationPresent(SAutowired.class)){ continue; }

            SAutowired autowired = field.getAnnotation(SAutowired.class);

            //如果用户没有自定义的beanName,就默认根据类型注入
            String autowiredBeanName = autowired.value().trim();
            if("".equals(autowiredBeanName)){
                //field.getType().getName() 获取字段的类型
                autowiredBeanName = field.getType().getName();
            }

            //暴力访问
            field.setAccessible(true);

            try {
                if(this.factoryBeanInstanceCache.get(autowiredBeanName) == null){
                    continue;
                }

                //ioc.get(beanName) 相当于通过接口的全名拿到接口的实现的实例
                field.set(instance,factoryBeanInstanceCache.get(autowiredBeanName).getWrapperedInstance());
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }

    }

    private Object initantiateBean(String beanName, SBeanDefinition beanDefinition) {
        String beanClassName = beanDefinition.getBeanClassName();
        Object instance = null;
        try {
            Class<?> clazz = Class.forName(beanClassName);
            instance = clazz.newInstance();

            // 如果是代理对象的话 触发AOP的逻辑

            // 缓存存一下
            this.factoryBeanObjectCache.put(beanName, instance);
            System.out.println("缓存【factoryBeanObjectCache】:" + beanName);
        }catch (Exception e){
            e.printStackTrace();
        }
        return instance;
    }

    @Override
    public Object getBean(Class<?> beanClass) {
        return getBean(beanClass.getName());
    }

    private void doLoadInstance() {
        for (Map.Entry<String, SBeanDefinition> entry : this.registry.beanDefinitionMap.entrySet()) {
            String beanName = entry.getKey();
            if (!entry.getValue().isLazyInit()) {
                getBean(beanName);
            }
        }
    }

    public int getBeanDefinitionCount(){
        return this.registry.beanDefinitionMap.size();
    }

    public String[] getBeanDefinitionNames(){
        return this.registry.beanDefinitionMap.keySet().toArray(new String[0]);
    }
}

core

package com.spring.framework.core;

public interface SBeanFactory {
    /**
     * 根据beanName获取对象
     * @param beanName
     * @return
     */
    Object getBean(String beanName);

    /**
     * 根据Class获取对象
     * @param beanClass
     * @return
     */
    Object getBean(Class<?> beanClass);
}

beans

package com.spring.framework.beans.config;

public class SBeanDefinition {
    // 是否延时加载
    // 默认否(false)
    public boolean isLazyInit(){
        return false;
    };
    private String factoryBeanName; // beanName
    private String beanClassName;   // 原生类的全类名

    public String getFactoryBeanName() {
        return factoryBeanName;
    }

    public void setFactoryBeanName(String factoryBeanName) {
        this.factoryBeanName = factoryBeanName;
    }

    public String getBeanClassName() {
        return beanClassName;
    }

    public void setBeanClassName(String beanClassName) {
        this.beanClassName = beanClassName;
    }

    @Override
    public String toString() {
        return "SBeanDefinition{" +
                "factoryBeanName='" + factoryBeanName + '\'' +
                ", beanClassName='" + beanClassName + '\'' +
                '}';
    }
}
package com.spring.framework.beans;

public class SBeanWrapper {
    private Object wrappedInstance;
    private Class<?> wrapperClass;

    public SBeanWrapper(Object instance) {
        this.wrappedInstance = instance;
        this.wrapperClass = instance.getClass();
    }

    public Object getWrapperedInstance() {
        return wrappedInstance;
    }

    public Class<?> getWrapperClass() {
        return wrapperClass;
    }
}

support

package com.spring.framework.support;

import com.spring.framework.beans.config.SBeanDefinition;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

public class SBeanDefinitionReader {
    // 保存用户配置好的配置文件
    private Properties contextConfig = new Properties();
    // 缓存从包路径下扫描的全类名, 需要被注册地BeanClass们
    private List<String> registryBeanClasses = new ArrayList<String>();

    public SBeanDefinitionReader(String... configLocations) {
        // 1、读取到配置文件(BeanDefinitionReader)
        doLoadConfig(configLocations[0]);
        // 2、扫描到相关的类,保存起来(BeanDefinitionReader)
        doScanner(contextConfig.getProperty("scanPackage"));
    }

    private void doScanner(String scanPackage) {
        //jar 、 war 、zip 、rar
        URL url = this.getClass().getClassLoader().getResource("/" + scanPackage.replaceAll("\\.","/"));
        File classPath = new File(url.getFile());

        //当成是一个ClassPath文件夹
        for (File file : classPath.listFiles()) {
            if(file.isDirectory()){
                doScanner(scanPackage + "." + file.getName());
            }else {
                if(!file.getName().endsWith(".class")){continue;}
                //全类名 = 包名.类名
                String className = (scanPackage + "." + file.getName().replace(".class", ""));
                //Class.forName(className);
                registryBeanClasses.add(className);
                System.out.println("扫描到相关的类【registryBeanClasses】:" + className);
            }
        }
    }

    private void doLoadConfig(String contextConfigLocation) {
        InputStream is = this.getClass().getClassLoader().getResourceAsStream(contextConfigLocation.replaceAll("classpath:", ""));
        try {
            contextConfig.load(is);
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            if(null != is){
                try {
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public List<SBeanDefinition> loadBeanDefinitions() {
        ArrayList<SBeanDefinition> result = new ArrayList<SBeanDefinition>();
        try {
            for (String className : registryBeanClasses) {
                Class<?> beanClass = Class.forName(className);
                // 1、如果是接口,不做处理
                if(beanClass.isInterface()){
                    continue;
                }
                // 2、默认类名首字母小写
                result.add(doCreateBeanDefinition(toLowerFirstCase(beanClass.getSimpleName()), beanClass.getName()));
                System.out.println("解析配置文件【beanDefinitions】:" + doCreateBeanDefinition(toLowerFirstCase(beanClass.getSimpleName()), beanClass.getName()).toString());
                //3、 如果有接口的话,就用实现类
                for (Class<?> i : beanClass.getInterfaces()) {
                    result.add(doCreateBeanDefinition(i.getName(), beanClass.getName()));
                    System.out.println("解析配置文件【beanDefinitions】:" + doCreateBeanDefinition(i.getName(), beanClass.getName()).toString());
                }
            }
        }catch (Exception e){
            e.printStackTrace();
        }
        return result;
    }

    private SBeanDefinition doCreateBeanDefinition(String beanName, String beanClassName) {
        SBeanDefinition beanDefinition = new SBeanDefinition();
        beanDefinition.setFactoryBeanName(beanName);
        beanDefinition.setBeanClassName(beanClassName);
        return beanDefinition;
    }

    //自己写,自己用
    private String toLowerFirstCase(String simpleName) {
        char [] chars = simpleName.toCharArray();
//        if(chars[0] > )
        chars[0] += 32;
        return String.valueOf(chars);
    }
}
package com.spring.framework.support;

import com.spring.framework.beans.config.SBeanDefinition;
import com.spring.framework.core.SBeanFactory;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class SDefaultListableBeanFactory implements SBeanFactory {
    public Map<String, SBeanDefinition> beanDefinitionMap = new HashMap<String, SBeanDefinition>();

    @Override
    public Object getBean(String beanName) {
        return null;
    }

    @Override
    public Object getBean(Class<?> beanClass) {
        return null;
    }

    public void doRegistBeanDefinition(List<SBeanDefinition> beanDefinitions) throws Exception {
        for (SBeanDefinition beanDefinition : beanDefinitions) {
            if(this.beanDefinitionMap.containsKey(beanDefinition.getFactoryBeanName())){
                throw new Exception("The " + beanDefinition.getFactoryBeanName() + "is exists!!!");
            }
            beanDefinitionMap.put(beanDefinition.getFactoryBeanName(), beanDefinition);
            System.out.println("缓存【SBeanDefinition】:" + beanDefinition.getFactoryBeanName());
        }
    }
}
posted @ 2022-03-30 10:58  Java-Legend  阅读(25)  评论(0编辑  收藏  举报