〔SPRING FRAMEWORK〕Dependencies

@(SPRING FRAMEWORK)

〔4〕7.4 Dependencies

声明:

  1. 斜体字:《官档》原文
  2. 斜体加粗字:《官档》原文的重点字、词、句
  3. 正体字+前置〔〕:个人表述行为,如:〔总结〕、〔分析〕等
  4. <samp style="color:#CCCCCC">灰体字:生词</samp>
  5. <samp style="color:#FF0066">粉体字:疑问</samp>

[TOC]

A typical enterprise application does not consist of a single object
〔总结〕一个典型的程序,是需要多个对象相互协作

how you go from defining a number of bean definitions that stand alone to a fully realized application where objects collaborate to achieve a goal.
〔总结〕定义一群具备相互协作能力的对象,以实现目标程序

1. Dependency Injection

Dependency injection (DI):is a process whereby objects define their dependencies, that is, the other objects they work with, only through constructor arguments, arguments to a factory method, or properties that are set on the object instance after it is constructed or returned from a factory method. The container then injects those dependencies when it creates the bean. This process is fundamentally the inverse, hence the name Inversion of Control (IoC), of the bean itself controlling the instantiation or location of its dependencies on its own by using direct construction of classes, or the Service Locator pattern.

1.1 Constructor-based dependency injection

<samp style="color:blue">关键词:</samp> <constructor-arg>

Constructor-based DI is accomplished by the container invoking a constructor with a number of arguments, each <samp style="color:#CCCCCC">representing</samp> a dependency.

Calling a static factory method with specific arguments to construct the bean is nearly <samp style="color:#CCCCCC">equivalent</samp>, and this discussion treats arguments to a constructor and to a static factory method similarly.

示例代码

public class SimpleMovieLister {

    // the SimpleMovieLister has a dependency on a MovieFinder
    private MovieFinder movieFinder;

    // a constructor so that the Spring container can inject a MovieFinder
    public SimpleMovieLister(MovieFinder movieFinder) {
        this.movieFinder = movieFinder;
    }

    // business logic that actually uses the injected MovieFinder is omitted...

}

〔总结〕基于构造函数的依赖注入,其核心在构造函数上,即重点需要放在一个疑问点上:<samp style="color: #FF0066">构造函数如何影响依赖注入(依赖注入的成功标准:一个bean对象已完成实例化)?</samp>

  1. 一个规范:顺序

示例代码

package x.y;

public class Foo {

    public Foo(Bar bar, Baz baz) {
        // ...
    }

}

第1种bean引用方式:引用引用类型

〔注意〕bean引用方式是指:容器在实例化化一个bean时,需要读取配置元数据。因为配置元数据中包含了可实例化一个POJO对象的所有必要数据

<!-- -->
<beans>
    <!-- 顺序一致 -->
    <bean id="foo" class="x.y.Foo">
        <constructor-arg ref="bar"/><!-- Foo(Bar bar,***) -->
        <constructor-arg ref="baz"/><!-- Foo(***,Baz baz) -->
    </bean>

    <bean id="bar" class="x.y.Bar"/>

    <bean id="baz" class="x.y.Baz"/>
</beans>

第2种bean引用方式:引用基本数据类型

package examples;

public class ExampleBean {

    // Number of years to calculate the Ultimate Answer
    private int years;

    // The Answer to Life, the Universe, and Everything
    private String ultimateAnswer;

    public ExampleBean(int years, String ultimateAnswer) {
        this.years = years;
        this.ultimateAnswer = ultimateAnswer;
    }

}

基于type属性

<!--  -->
<bean id="exampleBean" class="examples.ExampleBean">
    <constructor-arg type="int" value="7500000"/>
    <constructor-arg type="java.lang.String" value="42"/>
</bean>

基于name属性

<!-- -->
<bean id="exampleBean" class="examples.ExampleBean">
    <constructor-arg name="years" value="7500000"/>
    <constructor-arg name="ultimateAnswer" value="42"/>
</bean>

基于index属性

<!-- -->
<bean id="exampleBean" class="examples.ExampleBean">
    <constructor-arg index="0" value="7500000"/>
    <constructor-arg index="1" value="42"/>
</bean>

1.2 Setter-based dependency injection

<samp style="color:blue">关键词:</samp> no-argument

〔总结〕符合以下任一点,可选择基于setter的依赖注入

  1. 无参构造函数
  2. 无参工厂方法
public class SimpleMovieLister {

    // the SimpleMovieLister has a dependency on the MovieFinder
    private MovieFinder movieFinder;

    // a setter method so that the Spring container can inject a MovieFinder
    public void setMovieFinder(MovieFinder movieFinder) {
        this.movieFinder = movieFinder;
    }

    // business logic that actually uses the injected MovieFinder is omitted...

}

〔总结〕对比基于带参构造函数依赖注入和基于setter依赖注入,可以发现:基于构造函数的不需要提供setter/getter,基于setter的不需要提供带参构造函数

<samp style="color:#FF0066">Q: Constructor-based or setter-based DI?</samp>

Since you can <samp style="color:#CCCCCC">mix</samp> constructor-based and setter-based DI, it is a good rule of <samp style="color:#CCCCCC">thumb</samp> to use constructors for <samp style="color:#CCCCCC">mandatory</samp> dependencies and setter methods or configuration methods for <samp style="color:#cccccc">optional</samp> dependencies. Note that use of the @Required annotation on a setter method can be used to make the property a required dependency.

可以混搭一起用。根据实际开发经验,以Constructor-based DI为主,以setter-based DI为辅。主是强制,辅是可选。

The Spring team generally <samp style="color:#CCCCCC">advocates</samp> constructor injection as it enables one to implement application <samp style="color:#CCCCCC">components</samp> as <samp style="color:#CCCCCC">immutable</samp> objects and to ensure that required dependencies are not null. <samp style="color:#CCCCCC">Furthermore</samp> constructor-injected <samp style="color:#CCCCCC">components</samp> are always returned to client (calling) code in a fully initialized state. As a side note, a large number of constructor arguments is a bad code smell, implying that the class likely has too many responsibilities and should be <samp style="color:#CCCCCC">refactored</samp> to better address <samp style="color:#CCCCCC">proper separation</samp> of concerns.

Constructor-based DI能确保

Setter injection should <samp style="color:#cccccc">primarily</samp> only be used for optional dependencies that can be <samp style="color:#cccccc">assigned</samp> reasonable default values within the class. Otherwise, not-null checks must be performed everywhere the code uses the dependency. One benefit of setter injection is that setter methods make objects of that class <samp style="color:#cccccc">amenable</samp> to reconfiguration or re-injection later. Management through JMX MBeans is therefore a <samp style="color:#cccccc">compelling</samp> use case for setter injection.

Use the DI style that makes the most sense for a particular class. Sometimes, when dealing with third-party classes for which you do not have the source, the choice is made for you. For example, if a third-party class does not expose any setter methods, then constructor injection may be the only available form of DI.

〔总结〕懵逼¬_¬


1.3 Dependency resolution process

〔总结〕执行注入的步骤(详见《官档》):

  • ApplicationContext根据配置元数据装配所有bean对象
  • 当依赖的具体表现形式为以下时:

    • properties
    • constructor arguments
    • arguments to the static-factory method
      那么ApplicationContext会根据配置元数据的信息为POJO对象引用到对应的bean对象上。
  • 要保证在每个属性,参数构造函数能设值的时候,必须提供值,这个值:可以是基本值,也可以是引用值。
  • 每个属性、参数构造函数中值的类型都能够被Spring convert成字符串类型。

<samp style="color:#FF0066">如何解决Circular dependencies ?</samp>

Circular dependencies场景

  1. Class A requires an instance of class B through constructor injection, and class B requires an instance of class A through constructor injection.
  2. If you configure beans for classes A and B to be injected into each other, the Spring IoC container <samp style="color:#cccccc">detects</samp> this circular reference at runtime, and throws a <samp style="color:#ff0066">BeanCurrentlyInCreationException</samp>.

Circular dependencies异常解决方案:
you can configure circular dependencies with setter injection.


1.4 Examples of dependency injection

代码案例:参见《官档》




2. Dependencies and configuration in detail

2.1 Straight values

观察以下三个代码片段:

代码片段 1 使用最原始的方式

<bean id="myDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
    <!-- results in a setDriverClassName(String) call -->
    <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
    <property name="url" value="jdbc:mysql://localhost:3306/mydb"/>
    <property name="username" value="root"/>
    <property name="password" value="masterkaoli"/>
</bean>

代码片段 2 : 使用p-namespace配置元数据

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:p="http://www.springframework.org/schema/p"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="myDataSource" class="org.apache.commons.dbcp.BasicDataSource"
        destroy-method="close"
        p:driverClassName="com.mysql.jdbc.Driver"
        p:url="jdbc:mysql://localhost:3306/mydb"
        p:username="root"
        p:password="masterkaoli"/>

</beans>

代码片段 3:使用java.util.Properties

<bean id="mappings"
    class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">

    <!-- typed as a java.util.Properties -->
    <property name="properties">
        <value>
            jdbc.driver.className=com.mysql.jdbc.Driver
            jdbc.url=jdbc:mysql://localhost:3306/mydb
        </value>
    </property>
</bean>

<samp style="color:#ff0066">〔总结〕</samp>
<samp style="color:#ff0066">1. 阅读对应《官档》后,依旧对小标题#Straight values#的具体含义模糊不清,不清楚其牵引下文的意图是什么。</samp>
<samp style="color:#ff0066">2. 对比上文给出的3个代码片段,可发现:皆在用不同的方法进行元数据配置,并且被配置的具体对象是数据库驱动。</samp>


2.2 References to other beans

关键词:ref

The ref element is the final element inside a ① <constructor-arg/> or ② <property/> definition element.Here you set the value of the specified property of ③ a bean to be a reference to another bean (a collaborator) managed by the container. The referenced bean is a dependency of the bean whose property will be set, and it is initialized on demand as needed before the property is set. (If the collaborator is a singleton bean, it may be initialized already by the container.) All references are ultimately a reference to another object. Scoping and validation depend on whether you specify the id/name of the other object through the bean, local, or parent attributes.
〔总结〕从上文可得

  1. ref属性在哪用,有什么用
  2. 略提bean作用域、bean验证对bean对象的影响。

示例代码

<ref bean="someBean"/>
<!-- in the parent context -->
<bean id="accountService" class="com.foo.SimpleAccountService">
    <!-- insert dependencies as required as here -->
</bean>
<!-- in the child (descendant) context -->
<bean id="accountService" <!-- bean name is the same as the parent bean -->
    class="org.springframework.aop.framework.ProxyFactoryBean">
    <property name="target">
        <ref parent="accountService"/> <!-- notice how we refer to the parent bean -->
    </property>
    <!-- insert other configuration and dependencies as required here -->
</bean>

2.3 Inner beans

<bean id="outer" class="...">
    <!-- instead of using a reference to a target bean, simply define the target bean inline -->
    <property name="target">
        <bean class="com.example.Person"> <!-- this is the inner bean -->
            <property name="name" value="Fiona Apple"/>
            <property name="age" value="25"/>
        </bean>
    </property>
</bean>

〔总结〕inner bean类似于Java的内部类


2.4 Collections

  1. Collection merging
  2. Limitations of collection merging
  3. Strongly-typed collection
Spring Collections映射Java Collections
<list>——List
<set>——Set
<map>——Map
<props>——Properties

示例代码

<bean id="moreComplexObject" class="example.ComplexObject">
    <!-- results in a setAdminEmails(java.util.Properties) call -->
    <property name="adminEmails">
        <props>
            <prop key="administrator">administrator@example.org</prop>
            <prop key="support">support@example.org</prop>
            <prop key="development">development@example.org</prop>
        </props>
    </property>
    <!-- results in a setSomeList(java.util.List) call -->
    <property name="someList">
        <list>
            <value>a list element followed by a reference</value>
            <ref bean="myDataSource" />
        </list>
    </property>
    <!-- results in a setSomeMap(java.util.Map) call -->
    <property name="someMap">
        <map>
            <entry key="an entry" value="just some string"/>
            <entry key ="a ref" value-ref="myDataSource"/>
        </map>
    </property>
    <!-- results in a setSomeSet(java.util.Set) call -->
    <property name="someSet">
        <set>
            <value>just some string</value>
            <ref bean="myDataSource" />
        </set>
    </property>
</bean>

〔总结〕根据示例代码,得以下结论:
<map>keyvalue;<set>value也可以是用以下属性作为key或value值:

bean | ref | idref | list | set | map | props | value | null

2.5 Null and empty string values

示例代码:2种方式为字符串设置NULL或空值

设空值时, 第1种方式:

<bean class="ExampleBean">
    <property name="email" value=""/>
</bean>

设空值时, 第2种方式:

exampleBean.setEmail("")

设NULL时, 第1种方式:

<bean class="ExampleBean">
    <property name="email">
        <null/>
    </property>
</bean>

设NULL时, 第2种方式:

exampleBean.setEmail(null)

2.6 XML shortcut with the p-namespace

代码片段

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:p="http://www.springframework.org/schema/p"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd">
    
    <!--use standard XML format-->
    <bean name="classic" class="com.example.ExampleBean">
        <property name="email" value="foo@bar.com"/>
    </bean>
    
    <!--use the p_namespace-->
    <bean name="p-namespace" class="com.example.ExampleBean"
        p:email="foo@bar.com"/>
</beans>

代码片段 :使用p:spouse-ref=""

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:p="http://www.springframework.org/schema/p"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean name="john-classic" class="com.example.Person">
        <property name="name" value="John Doe"/>
        <property name="spouse" ref="jane"/>
    </bean>

    <bean name="john-modern"
        class="com.example.Person"
        p:name="John Doe"
        p:spouse-ref="jane"/>

    <bean name="jane" class="com.example.Person">
        <property name="name" value="Jane Doe"/>
    </bean>
</beans>

2.7 XML shortcut with the c-namespace

代码片段

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:c="http://www.springframework.org/schema/c"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="bar" class="x.y.Bar"/>
    <bean id="baz" class="x.y.Baz"/>

    <!-- traditional declaration -->
    <bean id="foo" class="x.y.Foo">
        <constructor-arg ref="bar"/>
        <constructor-arg ref="baz"/>
        <constructor-arg value="foo@bar.com"/>
    </bean>

    <!-- c-namespace declaration -->
    <bean id="foo" class="x.y.Foo" c:bar-ref="bar" c:baz-ref="baz" c:email="foo@bar.com"/>

</beans>

2.8 Compound property names

代码片段:确保fred,bob属性的值不为空,即确保不抛 NullPointerException异常

<bean id="foo" class="foo.Bar">
    <property name="fred.bob.sammy" value="123" />
</bean>



3. Using depends-on

depends-on的作用:
explicitly force one or more beans to be initialized before the bean using this element is initialized.

使用depends-on的场景:

  1. a static initializer in a class needs to be triggered.
  2. database driver registration

代码片段 1

<bean id="beanOne" class="ExampleBean" depends-on="manager"/>
<bean id="manager" class="ManagerBean" />

代码片段 2

<bean id="beanOne" class="ExampleBean" depends-on="manager,accountDao">
    <property name="manager" ref="manager" />
</bean>

<bean id="manager" class="ManagerBean" />
<bean id="accountDao" class="x.y.jdbc.JdbcAccountDao" />

〔总结〕参阅现有博客提供的博主,及具体应用场景




4. Lazy-initialized beans

延迟加载(初始化)bean对象。

By default, ApplicationContext implementations <samp style="color:#CCCCCC">eagerly</samp> create and configure all singleton beans as part of the initialization process. Generally, this <samp style="color:#CCCCCC">pre-instantiation</samp> is desirable, because errors in the configuration or surrounding environment are discovered immediately, as opposed to hours or even days later. When this behavior is not desirable, you can prevent pre-instantiation of a singleton bean by marking the bean definition as lazy-initialized. A lazy-initialized bean tells the IoC container to create a bean instance when it is first requested, rather than at startup.

代码示例

<bean id="lazy" class="com.foo.ExpensiveToCreateBean" lazy-init="true"/>
<bean name="not.lazy" class="com.foo.AnotherBean"/>

When the <samp style="color:#CCCCCC">preceding</samp> configuration is <samp style="color:#CCCCCC">consumed</samp> by an ApplicationContext, the bean named lazy is not <samp style="color:#CCCCCC">eagerly</samp> pre-instantiated when the ApplicationContext is starting up, <samp style="color:#CCCCCC">whereas</samp> the not.lazy bean is eagerly pre-instantiated.

However, when a lazy-initialized bean is a dependency of a singleton bean that is not lazy-initialized, the ApplicationContext creates the lazy-initialized bean at startup, because it must satisfy the singleton’s dependencies. The lazy-initialized bean is injected into a singleton bean elsewhere that is not lazy-initialized.

代码示例: 控制懒加载级别

<beans default-lazy-init="true">
    <!-- no beans will be pre-instantiated... -->
</beans>

〔总结〕参阅《官档》,多次阅读原文旨意。




5. Autowiring collaborators

  1. 自动装配的优势?
  2. 自动装配的劣势?
  3. 自动装配的模式?
  4. 自动装配的限制?
  5. 自动装配的应用?

〔总结〕Spring有能力自动装配协作者(即对象之间存在依赖关系)。
自动装配的优点:

  1. Autowiring can <samp style="color:#cccccc">significantly reduce</samp> the need to specify properties or constructor arguments.
  2. Autowiring can update a configuration as your objects <samp style="color:#cccccc">evolve</samp>. For example, if you need to add a dependency to a class, that dependency can be satisfied automatically without you needing to <samp style="color:#cccccc">modify</samp> the configuration.

〔理论总结〕使用自动装配后,配置文件具备自更新能力。主流开发的趋势之一。

autowire //基于XML

5.1 Limitations and disadvantages of autowiring

  1. <samp style="color:#cccccc">Explicit</samp> dependencies in property and constructor-arg settings always override autowiring. You cannot autowire <samp style="color:#cccccc">so-called</samp> simple properties such as <samp style="color:#cccccc">primitives</samp>, Strings, and Classes (and arrays of such simple properties). This limitation is by-design.
  2. Autowiring is less exact than explicit wiring. Although, as noted in the above table, Spring is careful to avoid guessing in case of <samp style="color:#cccccc">ambiguity</samp> that might have unexpected results, the relationships between your Spring-managed objects are no longer documented explicitly.
  3. Wiring information may not be available to tools that may generate documentation from a Spring container.
  4. Multiple bean definitions within the container may <samp style="color:#cccccc">match</samp> the type specified by the setter method or constructor argument to be autowired. For arrays, collections, or Maps, this is not necessarily a problem. However for dependencies that expect a single value, this <samp style="color:#cccccc">ambiguity</samp> is not <samp style="color:#cccccc">arbitrarily</samp> resolved. If no unique bean definition is available, an exception is thrown.

5.2 <samp style="color:#cccccc">Excluding</samp> a bean from autowiring

禁用某特定bean的自动装配功能

  1. 用法
  2. 作用
5.2.1 用法

基于XML

autowire-candidate=false 

基于注解

@Autowired
5.2.2 作用

unavailable to the autowiring infrastructure.
only affect type-based autowiring.

6. Method injection

主要用于解决以下场景:
在大多数应用场景中,bean对象一般都是单例对象。但在bean对象的依赖情况下:

  1. 一个单例依赖另一个单例
  2. 一个非单例依赖另一个非单例

古老的做法:是将一个bean定义为另一个bean的属性。以此建立依赖关系。

如:A-bean 依赖 B-bean,那么POJO可定义为:

public class A{
    public B b;
}

public class B{}

bean之间的依赖关系建立后,会产生一个问题: <samp style="color:#FF0066">两个bean的生命周期不一样,怎么办?</samp>
古老的做法是这样子的,见代码示例:
【代码示例说明】:

  1. CommandManager obejct在系统架构中属于业务逻辑层(SERVICE)
  2. CommadManger object的开放式方法process(Map commandState)的调用依赖Command obejct

根据【1.】和【2.】可得,两个类之间存在密切的依赖关系。所以Spring提供一种方式:当依赖方(CommandManager)的行为受制于被依赖方(Command)时,可以在<u>依赖方</u>内部实现<u>被依赖方</u>的初始化。完成上述行为的前提的是:依赖方(CommandManager)需要实现接口ApplicationContextAware

// a class that uses a stateful Command-style class to perform some processing
package fiona.apple;

// Spring-API imports
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

//依赖方(CommanderManager)现了ApplicationContextAware
public class CommandManager implements ApplicationContextAware {

    private ApplicationContext applicationContext;

    //process()的执行受制于Command对象
    public Object process(Map commandState) {
        
        Command command = createCommand();
       
        command.setState(commandState);
        
        return command.execute();
    }

    protected Command createCommand() {
        // notice the Spring API dependency!
        return this.applicationContext.getBean("command", Command.class);
    }

    public void setApplicationContext(
            ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }
}

这种做法需要你放弃Spring framework的IoC特性。以上述代码来看,bean object有两个:CommandManagerCommand。需要分析以下几个问题

  1. 两个bean object中,<u>依赖方</u>是谁? <u>被依赖方</u>又是谁?
    answer:依赖方:CommandManager; 被依赖方:Command
  2. 被依赖方的bean obejct的生命周期如何得到保证?
    answer:要保证被依赖方的生命周期随时不死。那么依赖方实现接口ApplicationContextAware,目的是为了调用Spring framework的方法

这种在业务层耦合Spring framework代码已破化IoC原则,因为在实现接口的那一刻起,IoC原则就已经被破坏了。即这种解决方案不可取。Spring给出了2种可靠的方案:

  1. lookup method injection
  2. arbitrary method replacement

〔经验之道〕业务层的所有代码应该满足以下注释要求

// no more Spring imports!
6.1 Lookup method injection

参阅《官档》,思考代码示例逻辑

6.2 Arbitrary method replacement

参阅《官档》,思考代码示例逻辑

spring-framework-3.0.5.RELEASE-dependencies 好不容易找到了,赶紧分享一下 因为不能大于20M,共分了8个包,都是独立的,我列了目录, 可以只下载需要的包,这是3号包: 1号包: edu.emory.mathcs.backport edu.oswego.cs.concurrent com.bea.commonj com.caucho com.google.jarjar com.h2database com.ibm.websphere com.jamonapi com.lowagie.text com.mchange.c3p0 com.opensymphony.quartz com.oracle.toplink.essentials com.springsource.bundlor com.springsource.util com.sun.syndication com.thoughtworks.xstream 2号包: net.sourceforge.serp net.sourceforge.xslthl org.antlr org.aopalliance javax.activation javax.annotation javax.ejb javax.el javax.faces javax.inject javax.jdo javax.jms javax.mail javax.persistence javax.portlet javax.resource javax.servlet javax.transaction javax.validation javax.xml.bind javax.xml.rpc javax.xml.soap javax.xml.stream javax.xml.ws net.sourceforge.cglib net.sourceforge.ehcache net.sourceforge.jasperreports net.sourceforge.jexcelapi net.sourceforge.jibx 3号包: org.apache.log4j org.apache.openjpa org.apache.axis org.apache.catalina org.apache.commons org.apache.coyote org.apache.ibatis org.apache.juli 4号包: org.apache.tiles org.apache.velocity org.apache.xerces org.apache.xml org.apache.xmlbeans org.apache.xmlcommons org.apache.derby org.apache.poi org.apache.struts org.apache.taglibs 5号包: org.codehaus.castor org.aspectj org.beanshell 6号包: org.jdom org.jgroups org.codehaus.groovy org.codehaus.jackson org.dom4j org.freemarker org.hibernate org.hsqldb org.jboss.javassist org.jboss.util 7号包: org.eclipse.persistence org.eclipse.jdt 8号包: org.osgi org.slf4j org.springframework org.springframework.build org.testng org.xmlpull org.joda org.jruby org.junit org.objectweb.asm
spring-framework-3.0.5.RELEASE-dependencies 好不容易找到了,赶紧分享一下 因为不能大于20M,共分了8个包,都是独立的,我列了目录, 可以只下载需要的包,这是8号包: 1号包: edu.emory.mathcs.backport edu.oswego.cs.concurrent com.bea.commonj com.caucho com.google.jarjar com.h2database com.ibm.websphere com.jamonapi com.lowagie.text com.mchange.c3p0 com.opensymphony.quartz com.oracle.toplink.essentials com.springsource.bundlor com.springsource.util com.sun.syndication com.thoughtworks.xstream 2号包: net.sourceforge.serp net.sourceforge.xslthl org.antlr org.aopalliance javax.activation javax.annotation javax.ejb javax.el javax.faces javax.inject javax.jdo javax.jms javax.mail javax.persistence javax.portlet javax.resource javax.servlet javax.transaction javax.validation javax.xml.bind javax.xml.rpc javax.xml.soap javax.xml.stream javax.xml.ws net.sourceforge.cglib net.sourceforge.ehcache net.sourceforge.jasperreports net.sourceforge.jexcelapi net.sourceforge.jibx 3号包: org.apache.log4j org.apache.openjpa org.apache.axis org.apache.catalina org.apache.commons org.apache.coyote org.apache.ibatis org.apache.juli 4号包: org.apache.tiles org.apache.velocity org.apache.xerces org.apache.xml org.apache.xmlbeans org.apache.xmlcommons org.apache.derby org.apache.poi org.apache.struts org.apache.taglibs 5号包: org.codehaus.castor org.aspectj org.beanshell 6号包: org.jdom org.jgroups org.codehaus.groovy org.codehaus.jackson org.dom4j org.freemarker org.hibernate org.hsqldb org.jboss.javassist org.jboss.util 7号包: org.eclipse.persistence org.eclipse.jdt 8号包: org.osgi org.slf4j org.springframework org.springframework.build org.testng org.xmlpull org.joda org.jruby org.junit org.objectweb.asm
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值