关于java:Spring框架

7次阅读

共计 16893 个字符,预计需要花费 43 分钟才能阅读完成。

这里所说的 Spring 框架是指 SSM 中的 Spring,Spring 是一个用于治理组件(Java 类)的容器,它蕴含并治理对象的生命周期。Spring 有两个核心技术,即 IOC 和 AOP。

  • IOC
    BeanFactory 接口提供了治理任意类型的对象的预约义机制,提供了一些根底性能。
    ApplicationContext 接口是对继承了 BeanFactory,它在 BeanFactory 的根底上实现更多的定制化的性能。该接口是 IOC 容器的具体体现,它负责实例化,配置和拆卸对象,这些对象以及对象之间的关系由配置文件(XML 文件,Java 正文)定义,容器会读取这些配置文件,从而创立和治理对象。
    只须要向 IOC 容器提供简略的 POJO 类以及配置文件,IOC 容器就会主动创立出对象并对对象进行治理
    IOC 容器创建对象:

    实例化容器,须要向 容器结构器 提供字符串模式的 bean 配置文件资源门路:
    实例化容器的同时,Spring 会读取 bean 配置文件并实例化 bean 配置文件中配置的类;应用时,只须要调用容器的 getBean 办法即可
    实例化容器并获取实例:

    // create and configure beans
    ApplicationContext context = new ClassPathXmlApplicationContext("services.xml", "daos.xml");
    
    // 拿到实例
    PetStoreService service = context.getBean("petStore", PetStoreService.class);
    
    // 应用实例
    List<String> userList = service.getUsernameList();

配置 xml 文件:
service.xml 的一个例子:

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

    <!-- services -->
    <!-- 实例化一个对象当时所需的配置 -->
    <!--id 是该 bean 的惟一辨认符,class 是须要被实例化的类的全限定类名 -->
    <bean id="petStore" class="org.springframework.samples.jpetstore.services.PetStoreServiceImpl">
        <!--property 对应类的各个属性,name 为属性名,ref: 属性值可能是另一个类实例化的对象,所以用 ref 来援用其它的 bean 的 id-->
        <!--ref 与 id 显示了合作类之间的依赖关系 -->
        <property name="accountDao" ref="accountDao"/>  
        <property name="itemDao" ref="itemDao"/>
        <!-- additional collaborators and configuration for this bean go here -->
    </bean>

    <!-- more bean definitions for services go here -->

</beans>

然而,实际上不应该应用 getBean 或者相似的办法来获取实例而是通过配置文件,应用依赖注入的办法应用实例
dao.xml 的例子
与 service.xml 基本相同

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

    <bean id="accountDao"
        class="org.springframework.samples.jpetstore.dao.jpa.JpaAccountDao">
        <!-- additional collaborators and configuration for this bean go here -->
    </bean>

    <bean id="itemDao" class="org.springframework.samples.jpetstore.dao.jpa.JpaItemDao">
        <!-- additional collaborators and configuration for this bean go here -->
    </bean>

    <!-- more bean definitions for data access objects go here -->

</beans>

让 bean 定义跨多文件也是常见的做法:

<beans>
    <!-- 为了应用定义在其它 xml 文件中的 bean,应用 **import** 标签引入其它 xml 配置文件,留神门路 -->
    <import resource="services.xml"/>
    <import resource="resources/messageSource.xml"/>
    <!-- 前斜杠会被疏忽,并且尽量不要应用前斜杠 -->
    <import resource="/resources/themeSource.xml"/>

    <bean id="bean1" class="..."/>
    <bean id="bean2" class="..."/>
</beans>

1.3.1 为 bean 起别名(不了解)

<alias name="myApp-dataSource" alias="subsystemA-dataSource"/>
<alias name="myApp-dataSource" alias="subsystemB-dataSource"/>

1.3.2 实例化 bean 的三种形式

办法一:应用构造函数进行实例化
在这种形式中,只须要满足 (1) 该类要有无参的构造函数,这一步是为了防止在实例化时间接提供属性的值,(2)提供各个属性的 get 和 set 办法,这一步是为了通过 <property> 标签为第一步中的实例的属性赋值
示例:

<bean id="exampleBean" class="examples.ExampleBean"/>

<bean name="anotherExample" class="examples.ExampleBeanTwo"/>

note:倡议当参数的数目超过四个时,就要提供无参的构造方法和为各个属性赋值的 get 和 set 办法,这样做的益处:
1. 不必在实例化对象时就给出属性值
2. 属性值能够灵便批改

办法二:应用动态工厂
这种办法不必创立工厂实例,因而工厂类中要有一个静态方法来创立 bean 实例。
配置实例:

<bean id="clientService"
    <!--class 指定动态工厂的全限定类名 -->
    class="examples.ClientService"
    <!--factory-method 指定返回 bean 实例的动态工厂办法 -->
    factory-method="createInstance"/>

动态工厂类示例:

public class ClientService {
    <!-- 创立 bean 实例 -->
    private static ClientService clientService = new ClientService();
    <!-- 这里的无参构造方法是上一行 new 一个 bean 实例用的 -->
    private ClientService() {}
    <!-- 返回 bean 实例的办法 -->
    public static ClientService createInstance() {return clientService;}
}

办法三:应用实例工厂进行实例化
该办法实际上创立了工厂对象,因而不须要有返回 bean 对象的静态方法
配置示例:

<!-- 先创立实例工厂的 bean -->
<bean id="serviceLocator" class="examples.DefaultServiceLocator">
    <!-- inject any dependencies required by this locator bean -->
</bean>

<!-- 再用实例工厂的 bean 创立指标 bean -->
<bean id="clientService"
    <!-- 指定实例工厂 bean,与动态工厂的区别是实例工厂在这里应用 factory-bean 而动态工厂在这里应用 class-->
    factory-bean="serviceLocator"
    <!-- 指定返回指标 bean 实例的工厂办法 -->
    factory-method="createClientServiceInstance"/>

实例工厂类示例:

public class DefaultServiceLocator {
    // 动态属性,类被加载的同时创立初始化该属性
    private static ClientService clientService = new ClientServiceImpl();
    // 须要创立工厂实例,因而返回 bean 实例的办法不必要是静态方法
    public ClientService createClientServiceInstance() {return clientService;}
}

另外,一个工厂也能够蕴含多个办法

1.4 依赖项
依赖就是类之间的调用关系,如果一个类 A 在它的外部应用了另一个类 B,那么就说这两个类之间产生了依赖。
依赖注入是个过程,就是将 B 类放入 A 类的这个过程,这个过程能够通过 A 类的构造函数实现,也能够通过 set 办法实现。

1.1.4 依赖注入

一、基于构造函数的依赖注入
基于构造函数的 DI 是通过容器调用具备多个参数的构造函数来实现的,每个参数代表一个依赖项。
容器是通过参数类型进行参数匹配的,如果 参数是不同类型并且没有继承关系 ,那么无需在 <constructor-arg/> 元素中显式指定结构函数参数索引或类型或名称。
例:

package x.y;

public class ThingOne {
    // 两个参数属于不同类
    public ThingOne(ThingTwo thingTwo, ThingThree thingThree) {// ...}
}
<beans>
    <bean id="beanOne" class="x.y.ThingOne">
        <!-- 无需在 constructor-arg 标签中进行任何显式提醒 -->
        <constructor-arg ref="beanTwo"/>
        <constructor-arg ref="beanThree"/>
    </bean>

    <bean id="beanTwo" class="x.y.ThingTwo"/>

    <bean id="beanThree" class="x.y.ThingThree"/>
</beans>

如果参数类型是 根本数据类型,因为提供的都是字符串,容器无奈辨认参数的指标类型,须要揭示容器参数的指标类型,而后 Spring 的类型转换能力将提供的字符串类型的值转换为指标类型

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

如果参数是 同种类型,能够应用索引进行提醒,索引下标从 0 开始

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

最好用的还是间接应用 结构函数参数名称(不是属性名)进行提醒

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

二、基于 set 办法的依赖注入
基于 Setter 的 DI 是通过容器在调用无参数构造函数或无参数 static 工厂办法来实例化 bean 后调用 bean 的 setter 办法来实现的。

<bean id="exampleBean" class="examples.ExampleBean">
    <!-- setter injection using the nested ref element -->
    <property name="beanOne">
        <ref bean="anotherExampleBean"/>
    </property>

    <!-- setter injection using the neater ref attribute -->
    <property name="beanTwo" ref="yetAnotherBean"/>
    <property name="integerProperty" value="1"/>
</bean>

<bean id="anotherExampleBean" class="examples.AnotherBean"/>
<bean id="yetAnotherBean" class="examples.YetAnotherBean"/>

总结:基于构造函数和基于动态工厂,基于工厂形式创立 Bean 实例的时候,都是通过 <constructor-arg/> 提供参数的,不同的是基于构造函数和动态工厂都是通过 class 指定类,而工厂办法是通过 factory-bean 指定的;基于 set 办法是通过 <property/> 提供参数的。
动态工厂注入:

<bean id="exampleBean" class="examples.ExampleBean" factory-method="createInstance">
    <constructor-arg ref="anotherExampleBean"/>
    <constructor-arg ref="yetAnotherBean"/>
    <constructor-arg value="1"/>
</bean>

<bean id="anotherExampleBean" class="examples.AnotherBean"/>
<bean id="yetAnotherBean" class="examples.YetAnotherBean"/>

基于构造函数和基于 set 办法能够混用,那么如何抉择呢?
举荐对于必须的属性,通过构造函数进行注入,而对于可选属性以及可能批改的属性,通过 get 办法进行注入

1.4.2 具体的依赖配置
idref 标签:援用另一个 bean 的 id 值,而不是真正的 bean 对象。

<bean id="theTargetBean" class="..."/>

<bean id="theClientBean" class="...">
    <property name="targetName">
        <idref bean="theTargetBean"/>
    </property>
</bean>

成果等同于下边的这个,然而能避免 theTargetBean 这个 bean 不存在而引起谬误

<bean id="theTargetBean" class="..." />

<bean id="client" class="...">
    <property name="targetName" value="theTargetBean"/>
</bean>

外部 bean, 它仅存在于一个 bean 的外部,其它 bean 无奈调用它,因而也不须要 id(即便设置了,容器也不会将它的 id 看作标识符)

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

汇合与汇合的合并

<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>

子 bean 中的汇合能够继承(合并)父 bean 中的汇合,如果汇合是有序的,父汇合中的元素会在子集合的元素之前

<beans>
    <bean id="parent" abstract="true" class="example.ComplexObject">
        <property name="adminEmails">
            <props>
                <prop key="administrator">administrator@example.com</prop>
                <prop key="support">support@example.com</prop>
            </props>
        </property>
    </bean>
    <bean id="child" parent="parent">
        <property name="adminEmails">
            <!-- the merge is specified on the child collection definition -->
            <props merge="true">
                <prop key="sales">sales@example.com</prop>
                <prop key="support">support@example.co.uk</prop>
            </props>
        </property>
    </bean>
<beans>

强类型汇合
如果在类中定义了汇合中元素的类型,那么在进行依赖注入时,Spring 的类型转换机制会主动的将传递的参数转换为适合的类型

public class SomeClass {

    private Map<String, Float> accounts;

    public void setAccounts(Map<String, Float> accounts) {this.accounts = accounts;}
}
<beans>
    <bean id="something" class="x.y.SomeClass">
        <property name="accounts">
            <map>
                <entry key="one" value="9.99"/>
                <entry key="two" value="2.75"/>
                <entry key="six" value="3.99"/>
            </map>
        </property>
    </bean>
</beans>

空和 null

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

等价于
exampleBean.setEmail("");

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

等价于
exampleBean.setEmail(null);

p 属性与 <property/> 标签能够替换,然而 p 属性不够灵便

<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
        https://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>

depends-on 属性能够设置创立和销毁的工夫依赖,实际上,depends-on 显式指定了一个类对另一个类的依赖关系,创立该 bean 前,会先创立被依赖的类的实例,销毁该 bean 前,也会先销毁被依赖的 bean 的实例。

<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" />

1.4.4 提早加载
容器在启动时会创立 bean 的单例:默认状况下,作为初始化过程的一部分,ApplicationContext 实现会急迫地创立和配置所有 单例 bean。通常,这种预实例化是可取的,因为配置或周围环境中的谬误会立刻发现,而不是几小时甚至几天之后提早加载 lazy-init 属性:将本来实例化 bean 的工夫从容器启动时提早到容器被第一次申请时

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

然而当提早加载的 bean 是另一个单例 bean 的依赖时,容器仍会在启动时创立该提早加载 bean 的实例,起因是要满足另一个 bean 的依赖关系,这种状况下能够应用容器级别的提早加载属性:default-lazy-init
1.4.5 主动拆卸
应用主动拆卸,Spring 通过 Java 的反射机制在实例化 bean 时能够主动的为 bean 的属性,办法入参拆卸。这时就不必在配置文件中手动配置关联类
主动拆卸属性:

package com.baobaotao;
import org.springframework.beans.factory.annotation.Autowired;

public class Boss {

    @Autowired
    private Car car;

    @Autowired
    private Office office;

    …
}

配置文件:

<!-- 该 BeanPostProcessor 将主动起作用,对标注 @Autowired 的 Bean 进行主动注入 -->
    <bean class="org.springframework.beans.factory.annotation.
        AutowiredAnnotationBeanPostProcessor"/>

    <!-- 移除 boss Bean 的属性注入配置的信息 -->
    <bean id="boss" class="com.baobaotao.Boss"/>
 
    <bean id="office" class="com.baobaotao.Office">
        <property name="officeNo" value="001"/>
    </bean>
    <bean id="car" class="com.baobaotao.Car" scope="singleton">
        <property name="brand" value="红旗 CA72"/>
        <property name="price" value="2000"/>
    </bean>

默认不应用主动拆卸,如果应用主动拆卸,默认是 byType, 除此之外还有 byName,constructor

bean 的作用范畴
容器创立的 bean 实例默认是单例的
容器在创立 bean 实例时,对于 bean 实例的范畴有四个可选项:
1.singleton 对于每个 Spring IoC 容器的单个 bean 实例的单个 bean 定义的范畴 只创立该 bean 的惟一实例,所有申请和援用都只应用这个实例
2.prototype 对于任何对象实例的单个 bean 定义的范畴,每次对该 bean 的申请都创立该 bean 的实例(向容器申请 ClassB,容器会创立并返回 ClassB 的实例:)

applicationContext.getBean(ClassB.class);

倡议将有状态(属性)的 bean 创立为 prototype,无状态的创立为单例模式
3.request 每次 HTTP 申请生命周期的单个 bean 定义范畴;即,每个 HTTP 申请返回一个 bean 实例。仅在 ApplicationContext 的上下文中无效

4.session 单个 bean 定义的 HTTP 会话生命周期的范畴。仅在 ApplicationContext 的上下文中无效

5.global session 单个 bean 定义的全局 HTTP 会话的生命周期。个别地在门户导入的信息组件的上下文中无效。仅在 ApplicationContext 的上下文中无效

6.application 单个 bean 定义的一个 ServletContext 的生命周期。仅在 ApplicationContext 的上下文中无效
与其余范畴相比,Spring 不治理原型 bean 的残缺生命周期。容器实例化、配置和以其余形式组装原型对象并将其传递给客户端由客户端进行治理,而没有该原型实例的进一步记录。因而原型 bean 所占用的资源要手动开释。

1.4.6 办法注入
管制反转:本来创建对象是一个对象须要另一个对象时,就显式的创立一个对象进去。管制反转是将对象的创立权交给容器,容器对立创立并治理对象,当一个对象须要依赖另一个对象时,容器将创立好的对象注入给它。
留神因为对象有单例的和非单例的(prototype),因而当一个单例的对象依赖另一个非单例的对象时,应用本来的注入办法就会呈现问题:单例对象仅在容器被初始化时创立一次,此时它依赖的非单例对象也被注入,后续应用单例对象时不会再创立新的非单例对象,这与非单例对象的初衷相违反,还会造成线程平安问题。

此时有两种解决办法
第一种:显式的调用 Spring 容器,创立一个新的 B 类的实例。
毛病是造成造成 Spring 的强耦合

@Component
public class ClassA implements ApplicationContextAware {
  private ApplicationContext applicationContext;
 
  public void printClass() {System.out.println("This is Class A:" + this);
    getClassB().printClass();
  }
 
  public ClassB getClassB() {return applicationContext.getBean(ClassB.class);
  }
 
  public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {this.applicationContext = applicationContext;}
}

第二种办法就是应用办法注入,这是针对办法的注入形式,容器会依据办法的返回值创立一个与办法返回值类型雷同的新的对象。从而不必显式的调用容器,实现解耦
基于注解:

@Component
public class ClassA {public void printClass() {System.out.println("This is Class A:" + this);
    getClassB().printClass();
  }
 
  @Lookup
  public ClassB getClassB() {return null;}
}

应用 @Lookup 标签对办法的签名有所要求,要满足:

<public|protected> [abstract] <return-type> theMethodName(no-arguments);

基于 xml:

package fiona.apple;

// no more Spring imports!

public abstract class CommandManager {public Object process(Object commandState) {
        // grab a new instance of the appropriate Command interface
        Command command = createCommand();
        // set the state on the (hopefully brand new) Command instance
        command.setState(commandState);
        return command.execute();}

    // okay... but where is the implementation of this method? 在 xml 文件中进行配置,容器会创立一个与该办法返回值类型雷同的对象
    protected abstract Command createCommand();}

xml 文件:

<!-- a stateful bean deployed as a prototype (non-singleton) -->
<bean id="myCommand" class="fiona.apple.AsyncCommand" scope="prototype">
    <!-- inject dependencies here as required -->
</bean>

<!-- commandProcessor uses statefulCommandHelper -->
<!--Lookup 是工作在类中的办法上的,这段配置的含意是:让 CommandManager 类中的 createCommand 办法返回一个 id 为 myCommand 的 bean 实例 -->
<bean id="commandManager" class="fiona.apple.CommandManager">
    <lookup-method name="createCommand" bean="myCommand"/>
</bean>

作用域 Bean 作为依赖项
当单例 bean 依赖于作用域 bean(request,session 等等)时,就会呈现问题。单例 bean 是在容器初始化时创立的,此时容器会试图注入单例 bean 依赖的作用域 bean,但因为此时还不在作用域 bean 的生命周期中(一次申请或者一次会话),因而作用域 bean 还没有被创立,所以依赖就会呈现谬误。
解决这一问题的办法是 应用代理 ,创立单例 bean 时注入依赖项的代理而不是依赖项自身(自身尚未被创立),该代理裸露与依赖项雷同的办法,因而单例 bean 会将它当作依赖项。当单例调用依赖项的办法时,真正的依赖项曾经被创立,代理会将调用交给真正的依赖项进行解决。
代理分为两类,一类是基于接口的代理(依赖项是一个接口);另一类是基于类的代理(依赖项是一个类);应用 xml 配置默认创立的是基于类的代理
基于类的代理:

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

    <!-- an HTTP Session-scoped bean exposed as a proxy -->
    <bean id="userPreferences" class="com.something.UserPreferences" scope="session">
        <!-- instructs the container to proxy the surrounding bean -->
        <aop:scoped-proxy/> 
    </bean>

    <!-- a singleton-scoped bean injected with a proxy to the above bean -->
    <bean id="userService" class="com.something.SimpleUserService">
        <!-- a reference to the proxied userPreferences bean -->
        <property name="userPreferences" ref="userPreferences"/>
    </bean>
</beans>

基于接口的代理

<!-- DefaultUserPreferences implements the UserPreferences interface -->
<bean id="userPreferences" class="com.stuff.DefaultUserPreferences" scope="session">
    <aop:scoped-proxy proxy-target-class="false"/>   <!-- 关掉基于类的代理即可 -->
</bean>

<bean id="userManager" class="com.stuff.UserManager">
    <property name="userPreferences" ref="userPreferences"/>
</bean>

1.6 自定义 bean 的性质
1.6.1 生命周期回调
回调由三种形式:1. 基于注解的形式;2. 基于 xml 配置文件;3. 实现接口
实现接口方式会造成耦合,因而不举荐应用这种形式
三种形式的执行程序(回调办法名不同时每种配置的办法都执行一次。如果办法名雷同,只执行一次)为:
初始化回调:类结构器 -> 注解——> 接口——>xml 配置
销毁回调: 注解——> 接口——>xml 配置
三种办法的示例:
1. 基于注解

public class User {
    @PostConstruct
    public void init() {// 增加初始化动作}

}

基于 xml

public class ExampleBean {public void init() {// do some initialization work}
}
<bean id="exampleInitBean" class="examples.ExampleBean" init-method="init"/>

基于继承

public class AnotherExampleBean implements InitializingBean {

    @Override
    public void afterPropertiesSet() {// do some initialization work}
}

Spring 容器保障在为 bean 提供所有依赖项后立刻调用配置的初始化回调,这意味着 AOP 拦截器等尚未利用于 bean。

1.6.2 ApplicationContextAware 和 BeanNameAware
能够通过实现 ApplicationContextAware 接口来获取 ApplicationContext(容器),然而不举荐应用这种形式,因为会造成代码和 Spring 框架的耦合(代码晓得了 Spring 的存在),举荐应用主动拆卸形式获取。

主动拆卸形式
只须要在类中定义 ApplicationContext 属性,并在该属性上增加 @Autowired 标签,框架就会在容器中寻找与该属性相匹配的对象(byType,byName)

@Autowired
ApplicationContext context;

ApplicationContextAware 接口

public interface ApplicationContextAware {void setApplicationContext(ApplicationContext applicationContext) throws BeansException;

还有一种形式是通过监听器获取 ApplicationContext 对象
https://blog.csdn.net/asd0001…

1.7 Bean 继承
子 bean 能够继承父 bean 的范畴,构造函数参数值,属性值,并且能够抉择增加新值。为子 bean 指定的范畴,初始化办法,销毁办法和动态工厂办法都会笼罩父 bean 的设置。
如果将父 bean 设置为形象 bean,那么该父 bean 将专门用于被继承,不能被实例化。

<bean id="inheritedTestBeanWithoutClass" abstract="true">  <!-- 将该 bean 设置为形象类型,不能创立实例 -->
    <property name="name" value="parent"/>
    <property name="age" value="1"/>
</bean>

<bean id="inheritsWithClass" class="org.springframework.beans.DerivedTestBean"
        parent="inheritedTestBeanWithoutClass" init-method="initialize">  <!-- 指定了初始化办法,该指定会笼罩父 bean 中的设置 -->
    <property name="name" value="override"/>
    <!-- age will inherit the value of 1 from the parent bean definition-->
</bean>
正文完
 0