Spring Ioc容器-Bean(一)

Bean的命名

Bean在Ioc容器中能够有一个或多个名称,但这些名称在容器内必须惟一,在Xml中配置id和name属性就能够为Bean起别名。html

<bean id="user" name="zhangsan,lisi" class="com.example.demo.spring.UserBean"/>java

这样咱们就能够经过名称user、zhangsan、lisi获取UserBean的实例。web

固然若是你没有给UserBean配置id/name属性,Spring Ioc容器会未Bean自动生成一个类名首字符小写的别名。spring

除此以外还可使用<alias name="user" alias="wangwu"></alias配置别名。websocket

Bean的实例化

<bean class=""/>class属性表明着Ioc要实例化的Bean的类型,一般Ioc容器会经过反射机制调用其无参构造函数直接建立Bean。session

除此以外还能够配置使用静态工厂方法或者实例工厂方法来实例化对象。app

/**
 * 使用静态工厂实例化Bean
 * 配置factory-method属性
 */
public class StaticFactory {

    private static UserBean userBean = new UserBean();

    public static UserBean createInstance() {
        return userBean;
    }
}
<bean id="user1" class="com.example.demo.spring.StaticFactory" factory-method="createInstance"></bean>

使用class来指定包含static工厂方法的类型,使用factory-method指定建立bean实例的工厂方法。socket

/**
 * 实例工厂方法
 * 配置factory-bean和factory-method属性
 */
public class InstanceFactory {

    public UserBean createUserBeanInstance() {
        return new UserBean();
    }
}

<bean id="instanceFactory" class="com.example.demo.spring.InstanceFactory"></bean> <bean id="user2" factory-bean="instanceFactory" factory-method="createUserBeanInstance"></bean>ide

使用factory-bean指定要建立Bean实例的方法的Bean的名称,使用factory-method指定工厂方法名称。函数

Bean依赖注入

依赖注入指Ioc要建立A的实例,但A内部又依赖于B的实例,依赖注入主要有两种类型:基于构造函数的依赖注入和基于Setter的依赖注入。

  • 构造函数注入

        基于构造函数的依赖注入主要依赖于<constructor-arg></constructor-ar标签。

  • 使用type属性显式指定了构造函数参数的类型
<bean id="user" class="com.example.demo.spring.UserBean">
    <constructor-arg type="java.lang.Integer" value="15"></constructor-arg>
</bean>

指定type的配置为Integer而且只有一个参数,因此Ioc在建立UserBean实例是会使用以下的构造函数

 

public UserBean(Integer age) {
    this.age = age;
    System.out.println("1");
}
  • 使用index属性来显式指定构造函数参数的索引
    <bean id="user" class="com.example.demo.spring.UserBean">
<!--        <constructor-arg type="java.lang.Integer" value="15"></constructor-arg>-->
        <constructor-arg index="0" value="16"></constructor-arg>
        <constructor-arg index="1" value="张三"></constructor-arg>
    </bean>

指定了有两个参数,因此会使用以下构造函数

public UserBean(Integer age, String name) {
    this.age = age;
    this.name = name;
    System.out.println("2");
}
  • 使用构造函数参数名称
<bean id="user" class="com.example.demo.spring.UserBean">
    <constructor-arg name="age" value="85"></constructor-arg>
</bean>

 Setter注入

        使用Setter注入,必须保证要注入的属性具备setter方法,setter方法能够利用idea自动生成。主要依赖于<property></property>

<bean id="user" class="com.example.demo.spring.UserBean">
    <property name="name" value="张三"></property>
    <property name="age" value="18"></property>
</bean>
  • list属性的配置
<bean id="user" class="com.example.demo.spring.UserBean">
    <property name="phone">
        <list>
            <value>123456789</value>
            <value>99999</value>
            <ref bean="user1"></ref>
        </list>
    </property>
</bean>
  • Map属性的配置
<property name="someMap">
 <map>
 <entry key="an entry" value="just some string"/>
 <entry key ="a ref" value-ref="myDataSource"/>
 </map>
 </property>

Bean的做用域

bean的做用域经过scope属性配置

scope 描述
singleton Spring Ioc容器中只有一个实例
prototype 每次获取bena实例都从新建立一个新的
request HTTP 请求的生命周期
session HTTP Session的生命周期
application ServletContext的生命周期
websocket WebSocket的生命周期

Bean的生命周期回调

  • InitializingBean: Bean在初始化时调用,等价于init-method属性和@PostConstruct注解,若是不指定初始化方法,Spring 默认会调用init()方法
  • DisposableBean:Bean在销毁时调用,等价于destroy-method属性和@PreDestroy注解,Spring 默认调用destroy()方法
  • Lifecycle:容器启动或关闭时回调,该回调是经过 LifecycleProcessor 完成回调
  • ApplicationContextAware:自动获取ApplicationContext的引用
  • BeanNameAware:获取该对象在Ioc容器中的名称,该方法在调用 afterPropertiesSet 或自定义的 init-method 以前调用

除此以外还有其余的Aware,功能是为了得到接口申明的依赖

name dependency
ApplicationEventPublisherAware ApplicationContext的事件发布者
BeanFactoryAware Bean工厂
ServletConfigAware 容器中的ServletConfig(Web容器)
ServletContextAware 容器中运行的ServletContext(Web容器)
BeanClassLoaderAware Bean的类加载器

 Bean的parent属性

parent属性用来指定要继承的配置数据,parent所指向的bean的定义必需要指定abstract属性为true,声明为抽象定义的Bean不能经过id获取实例,parent中定义的属性若是子bean从新配置,则会覆盖父bean的配置。

<bean id="inheritedTestBean" abstract="true" class="com.example.demo.spring.TestBean">
    <property name="name" value="parent"></property>
    <property name="age" value="1"></property>
</bean>

<bean id="inheritedTestBean" abstract="true">
    <property name="name" value="parent"></property>
    <property name="age" value="1"></property>
</bean>

<bean id="inheritsWithDifferentClass" class="com.example.demo.spring.DrivedTestBean" parent="inheritedTestBean">
    <property name="name" value="override"></property>
    <property name="addr" value="西安"></property>
</bean>

Bean的扩展

  • BeanPostProcessor

BeanPostProcessor接口提供了两个方法postProcessBeforeInitialization(init以前调用)postProcessAfterInitialization (init以后调用),主要为了在Spring容器完成实例化、配置和初始化以后实现一些自定义的实例化或依赖解析逻辑等。一个容器中能够注册多个BeanPostProcessor,要控制他们的执行顺序,只须要继承Ordered接口。

public class InstantiationTracingBeanPostProcessor implements BeanPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("************postProcessBeforeInitialization*********** + " + beanName);
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("************postProcessAfterInitialization*********** + " + beanName);
        return bean;
    }
}
  • BeanFactoryPostProcessor

     BeanFactoryPostProcessor是用来在beans进行初始化前修改bean的配置元数据。与BeanPostProcessor的主要区别是:BeanPostProcessor对Bean实例进行操做,BeanFactoryPostProcessor是对Bean的配置元数据进行操做。

public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor, Ordered {

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
        System.out.println("postProcessBeanFactory >>>");
        BeanDefinition beanDefinition = configurableListableBeanFactory.getBeanDefinition("message1");
        System.out.println(beanDefinition.getBeanClassName());
    }

    @Override
    public int getOrder() {
        return 1;
    }

    public void init() {
        System.out.println("MyBeanFactoryPostProcessor init");
    }
}
  • PropertyPlaceholderConfigurer

PropertyPlaceholderConfigurer 能够从单独独文件中的 bean 定义外部化属性值,不一样的环境中加载不一样的配置文件。

<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
    <property name="locations" value="jdbc.properties"></property>
</bean>
<bean id="datasource" class="com.example.demo.spring.DataSource">
    <property name="userName" value="${datasource.userName}"></property>
    <property name="password" value="${datasource.password}"></property>
</bean>

也可使用


<context:property-placeholder location="classpath:com/something/jdbc.properties"/>
  • PropertyOverrideConfigure

用来覆盖Bean的属性。

<bean class="org.springframework.beans.factory.config.PropertyOverrideConfigurer">
    <property name="locations" value="jdbc.properties"></property>
</bean>
<bean id="datasource" class="com.example.demo.spring.DataSource">
    <property name="password" value="12311"></property>
</bean>

jdbc.properties

datasource.userName=root
datasource.password=root

最终Bean password值会是root被PropertyOverrideConfigurer覆盖。

FactoryBean

FactoryBean是一个特殊的接口,它不一样于BeanFactory,BeanFacoty是Spring的工厂,而FactoryBean是容器中的一个特殊bean,能够建立指定的类型Bean的实例。

public class DataSourceFanctoryBean implements FactoryBean<DataSource> {
    @Override
    public DataSource getObject() throws Exception {
        System.out.println(1);
        DataSource dataSource = new DataSource();
        dataSource.setUserName("张三");
        dataSource.setPassword("123456");
        return dataSource;
    }

    @Override
    public Class<?> getObjectType() {
        return DataSource.class;
    }

    @Override
    public boolean isSingleton() {
        return false;
    }
}
<bean id="datasource" class="com.example.demo.spring.DataSourceFanctoryBean"></bean>

直接经过beanfactory.getBean("datasource")获取则是 DataSource 的实例,在id前加 & 则获取的是 DataSourceFanctoryBean 的实例
相关文章
相关标签/搜索