我们为什么要学习框架?这些框架到底从何而来?框架的本质是什么?使用框架,又能给我们的开发带来什么样的好处呢?
拿struts2来说,我们在web项目中引入struts2时,除了引入必要的jar包,我们需要在web.xml中配置一段代码,即:
<filter>
<!-- 配置Struts2核心Filter的名字 -->
<filter-name>struts2</filter-name>
<!-- 配置Struts2核心Filter的实现类 -->
<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
</filter>
<!-- 配置Filter拦截的URL -->
<filter-mapping>
<!-- 配置Struts2的核心FilterDispatcher拦截所有用户请求 -->
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
这个是引入struts2必须加入的,那么引入这段代码,Struts究竟干了什么。从这个类的名字即StrutsPrepareAndExecuteFilter我们可以看出,是Struts准备和执行的拦截器,后面当我们深入源码时就会发现,他确实创建了两个对象,一个是准备,一个是执行,这两个对象像两条生产线,一个是原材料的准备,一个是拿原材料生产产品。首先我们看一下项目加载进Tomcat,服务器启动的日志信息。
九月 30, 2016 9:37:39 上午 org.apache.catalina.core.AprLifecycleListener init
信息: Loaded APR based Apache Tomcat Native library 1.1.22.
九月 30, 2016 9:37:39 上午 org.apache.catalina.core.AprLifecycleListener init
信息: APR capabilities: IPv6 [false], sendfile [true], accept filters [false], random [true].
九月 30, 2016 9:37:41 上午 org.apache.coyote.AbstractProtocol init
信息: Initializing ProtocolHandler ["http-apr-8080"]
九月 30, 2016 9:37:41 上午 org.apache.coyote.AbstractProtocol init 从日志看出这是catalina初始化和启动过程
信息: Initializing ProtocolHandler ["ajp-apr-8009"]
九月 30, 2016 9:37:41 上午 org.apache.catalina.startup.Catalina load
信息: Initialization processed in 2089 ms
九月 30, 2016 9:37:41 上午 org.apache.catalina.core.StandardService startInternal
信息: Starting service Catalina
九月 30, 2016 9:37:41 上午 org.apache.catalina.core.StandardEngine startInternal
信息: Starting Servlet Engine: Apache Tomcat/7.0.25
九月 30, 2016 9:37:41 上午 org.apache.catalina.startup.HostConfig deployDirectory
信息: Deploying web application directory E:\apache-tomcat-7.0.25\webapps\docs
九月 30, 2016 9:37:41 上午 org.apache.catalina.startup.HostConfig deployDirectory
信息: Deploying web application directory E:\apache-tomcat-7.0.25\webapps\examples
九月 30, 2016 9:37:42 上午 org.apache.catalina.core.ApplicationContext log
信息: ContextListener: contextInitialized()
九月 30, 2016 9:37:42 上午 org.apache.catalina.core.ApplicationContext log
信息: SessionListener: contextInitialized()
九月 30, 2016 9:37:42 上午 org.apache.catalina.core.ApplicationContext log
信息: ContextListener: attributeAdded('org.apache.jasper.compiler.TldLocationsCache', 'org.apache.jasper.compiler.TldLocationsCache@737612')
九月 30, 2016 9:37:42 上午 org.apache.catalina.startup.HostConfig deployDirectory
信息: Deploying web application directory E:\apache-tomcat-7.0.25\webapps\host-manager
九月 30, 2016 9:37:42 上午 org.apache.catalina.startup.HostConfig deployDirectory
信息: Deploying web application directory E:\apache-tomcat-7.0.25\webapps\manager
九月 30, 2016 9:37:42 上午 org.apache.catalina.startup.HostConfig deployDirectory
信息: Deploying web application directory E:\apache-tomcat-7.0.25\webapps\ROOT
九月 30, 2016 9:37:42 上午 org.apache.catalina.startup.HostConfig deployDirectory
信息: Deploying web application directory E:\apache-tomcat-7.0.25\webapps\service
九月 30, 2016 9:37:42 上午 org.apache.catalina.core.ApplicationContext log
信息: ContextListener: contextInitialized()
九月 30, 2016 9:37:42 上午 org.apache.catalina.core.ApplicationContext log
信息: SessionListener: contextInitialized()
九月 30, 2016 9:37:42 上午 org.apache.catalina.core.ApplicationContext log
信息: ContextListener: attributeAdded('org.apache.jasper.compiler.TldLocationsCache', 'org.apache.jasper.compiler.TldLocationsCache@1cbbeb1')
九月 30, 2016 9:37:42 上午 org.apache.catalina.startup.HostConfig deployDirectory
信息: Deploying web application directory E:\apache-tomcat-7.0.25\webapps\struts2 我Tomcat下webapp项目
九月 30, 2016 9:37:43 上午 com.opensymphony.xwork2.util.logging.jdk.JdkLogger info
信息: Parsing configuration file [struts-default.xml]
九月 30, 2016 9:37:43 上午 com.opensymphony.xwork2.util.logging.jdk.JdkLogger info
信息: Unable to locate configuration files of the name struts-plugin.xml, skipping
九月 30, 2016 9:37:43 上午 com.opensymphony.xwork2.util.logging.jdk.JdkLogger info
信息: Parsing configuration file [struts-plugin.xml]
九月 30, 2016 9:37:43 上午 com.opensymphony.xwork2.util.logging.jdk.JdkLogger info
信息: Parsing configuration file [struts.xml]
九月 30, 2016 9:37:43 上午 com.opensymphony.xwork2.util.logging.jdk.JdkLogger info
信息: Choosing bean (struts) for (com.opensymphony.xwork2.ObjectFactory)
九月 30, 2016 9:37:43 上午 com.opensymphony.xwork2.util.logging.jdk.JdkLogger info
信息: Choosing bean (struts) for (com.opensymphony.xwork2.FileManagerFactory)
九月 30, 2016 9:37:43 上午 com.opensymphony.xwork2.util.logging.jdk.JdkLogger info
信息: Choosing bean (struts) for (com.opensymphony.xwork2.conversion.impl.XWorkConverter)
九月 30, 2016 9:37:43 上午 com.opensymphony.xwork2.util.logging.jdk.JdkLogger info
信息: Choosing bean (struts) for (com.opensymphony.xwork2.conversion.impl.CollectionConverter)
九月 30, 2016 9:37:43 上午 com.opensymphony.xwork2.util.logging.jdk.JdkLogger info
信息: Choosing bean (struts) for (com.opensymphony.xwork2.conversion.impl.ArrayConverter)
九月 30, 2016 9:37:43 上午 com.opensymphony.xwork2.util.logging.jdk.JdkLogger info
信息: Choosing bean (struts) for (com.opensymphony.xwork2.conversion.impl.DateConverter)
九月 30, 2016 9:37:43 上午 com.opensymphony.xwork2.util.logging.jdk.JdkLogger info
信息: Choosing bean (struts) for (com.opensymphony.xwork2.conversion.impl.NumberConverter)
九月 30, 2016 9:37:43 上午 com.opensymphony.xwork2.util.logging.jdk.JdkLogger info
信息: Choosing bean (struts) for (com.opensymphony.xwork2.conversion.impl.StringConverter)
九月 30, 2016 9:37:43 上午 com.opensymphony.xwork2.util.logging.jdk.JdkLogger info
信息: Choosing bean (struts) for (com.opensymphony.xwork2.conversion.ConversionPropertiesProcessor)
web.xml是在Tomcat启动时就被加载进去了,上面的日志并没有体现出web.xml在什么时候被加载,但我们发现了struts2的配置文件struts-default.xml、struts-plugin.xml、struts.xml文件被依次加载,所以他们的配置是一个向前覆盖的过程,后面的覆盖前面的。那究竟struts-default.xml中有什么呢?那我们先看看源码再说:
<struts>
<constant name="struts.excludedClasses"
value="
java.lang.Object,
java.lang.Runtime,
java.lang.System,
java.lang.Class,
java.lang.ClassLoader,
java.lang.Shutdown,
java.lang.ProcessBuilder,
ognl.OgnlContext,
ognl.ClassResolver,
ognl.TypeConverter,
ognl.MemberAccess,
ognl.DefaultMemberAccess,
com.opensymphony.xwork2.ognl.SecurityMemberAccess,
com.opensymphony.xwork2.ActionContext" />
<!-- this must be valid regex, each '.' in package name must be escaped! -->
<!-- it's more flexible but slower than simple string comparison -->
<!-- constant name="struts.excludedPackageNamePatterns" value="^java\.lang\..*,^ognl.*,^(?!javax\.servlet\..+)(javax\..+)" / -->
<!-- this is simpler version of the above used with string comparison -->
<constant name="struts.excludedPackageNames" value="java.lang.,ognl,javax" />
<bean class="com.opensymphony.xwork2.ObjectFactory" name="struts"/>
<bean type="com.opensymphony.xwork2.factory.ResultFactory" name="struts" class="org.apache.struts2.factory.StrutsResultFactory" />
<bean type="com.opensymphony.xwork2.factory.ActionFactory" name="struts" class="com.opensymphony.xwork2.factory.DefaultActionFactory" />
<bean type="com.opensymphony.xwork2.factory.ConverterFactory" name="struts" class="com.opensymphony.xwork2.factory.DefaultConverterFactory" />
<bean type="com.opensymphony.xwork2.factory.InterceptorFactory" name="struts" class="com.opensymphony.xwork2.factory.DefaultInterceptorFactory" />
<bean type="com.opensymphony.xwork2.factory.ValidatorFactory" name="struts" class="com.opensymphony.xwork2.factory.DefaultValidatorFactory" />
<bean type="com.opensymphony.xwork2.factory.UnknownHandlerFactory" name="struts" class="com.opensymphony.xwork2.factory.DefaultUnknownHandlerFactory" />
<bean type="com.opensymphony.xwork2.FileManager" class="com.opensymphony.xwork2.util.fs.DefaultFileManager" name="system" scope="singleton"/>
<bean type="com.opensymphony.xwork2.FileManagerFactory" class="com.opensymphony.xwork2.util.fs.DefaultFileManagerFactory" name="struts" scope="singleton"/>
<bean type="com.opensymphony.xwork2.ActionProxyFactory" name="struts" class="org.apache.struts2.factory.StrutsActionProxyFactory"/>
<bean type="com.opensymphony.xwork2.ActionProxyFactory" name="prefix" class="org.apache.struts2.factory.PrefixBasedActionProxyFactory"/>
<bean type="com.opensymphony.xwork2.conversion.ObjectTypeDeterminer" name="struts" class="com.opensymphony.xwork2.conversion.impl.DefaultObjectTypeDeterminer"/>
<bean type="com.opensymphony.xwork2.util.PatternMatcher" name="struts" class="com.opensymphony.xwork2.util.WildcardHelper" />
<bean type="com.opensymphony.xwork2.util.PatternMatcher" name="namedVariable" class="com.opensymphony.xwork2.util.NamedVariablePatternMatcher"/>
<bean type="com.opensymphony.xwork2.util.PatternMatcher" name="regex" class="org.apache.struts2.util.RegexPatternMatcher"/>
<bean type="org.apache.struts2.util.ContentTypeMatcher" name="struts" class="org.apache.struts2.util.DefaultContentTypeMatcher"/>
<bean type="org.apache.struts2.dispatcher.mapper.ActionMapper" name="struts" class="org.apache.struts2.dispatcher.mapper.DefaultActionMapper" />
<bean type="org.apache.struts2.dispatcher.mapper.ActionMapper" name="composite" class="org.apache.struts2.dispatcher.mapper.CompositeActionMapper" />
<bean type="org.apache.struts2.dispatcher.mapper.ActionMapper" name="restful" class="org.apache.struts2.dispatcher.mapper.RestfulActionMapper" />
<bean type="org.apache.struts2.dispatcher.mapper.ActionMapper" name="restful2" class="org.apache.struts2.dispatcher.mapper.Restful2ActionMapper" />
<bean type="org.apache.struts2.dispatcher.multipart.MultiPartRequest" name="jakarta" class="org.apache.struts2.dispatcher.multipart.JakartaMultiPartRequest" scope="prototype"/>
<bean type="org.apache.struts2.dispatcher.multipart.MultiPartRequest" name="jakarta-stream" class="org.apache.struts2.dispatcher.multipart.JakartaStreamMultiPartRequest" scope="prototype"/>
<bean type="org.apache.struts2.views.TagLibraryDirectiveProvider" name="s" class="org.apache.struts2.views.DefaultTagLibrary" />
<bean type="org.apache.struts2.views.TagLibraryModelProvider" name="s" class="org.apache.struts2.views.DefaultTagLibrary" />
<bean class="org.apache.struts2.views.freemarker.FreemarkerThemeTemplateLoader" />
<bean class="org.apache.struts2.views.freemarker.FreemarkerManager" name="struts" />
<bean class="org.apache.struts2.views.velocity.VelocityManager" name="struts" optional="true" />
从部分代码我们可以看出,大多都是bean,里面包含类的全路径,所以我们想到了,框架在加载时,肯定是利用java反射机制,将这些类加载进框架中,很多人会想,这就是框架的本质,不就是利用反射将类加载一下,很简单啊,但是,加载以后,类的创建、类与类之间的关系我们怎么去维护,加载单一的类很容易,但是当类很多并且他们之间的关系很复杂时,我们怎么办?我们如何去加载,我们如何去维护他们之间的关系?那么类与类之间到底有什么关系呢?下节再述。