本篇内容主要讲解“如何理解Spring Ioc容器Bean”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“如何理解Spring Ioc容器Bean”吧!
Bean在Ioc容器中可以有一个或多个名称,但这些名称在容器内必须唯一,在Xml中配置id和name属性就可以为Bean起别名。
<bean id="user" name="zhangsan,lisi" class="com.example.demo.spring.UserBean"/>
这样我们就可以通过名称user、zhangsan、lisi获取UserBean的实例。
当然如果你没有给UserBean配置id/name属性,Spring Ioc容器会未Bean自动生成一个类名首字符小写的别名。
除此之外还可以使用<alias name="user" alias="wangwu"></alias
配置别名。
<bean class=""/>
class属性代表着Ioc要实例化的Bean的类型,通常Ioc容器会通过反射机制调用其无参构造函数直接创建Bean。
除此之外还可以配置使用静态工厂方法或者实例工厂方法来实例化对象。
/** * 使用静态工厂实例化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实例的工厂方法。
/** * 实例工厂方法 * 配置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>
使用factory-bean指定要创建Bean实例的方法的Bean的名称,使用factory-method指定工厂方法名称。
依赖注入指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的作用域通过scope属性配置
scope | 描述 |
singleton | Spring Ioc容器中只有一个实例 |
prototype | 每次获取bena实例都重新创建一个新的 |
request | HTTP 请求的生命周期 |
session | HTTP Session 的生命周期 |
application | ServletContext 的生命周期 |
websocket | WebSocket 的生命周期 |
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的类加载器 |
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>
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=rootdatasource.password=root
最终Bean password值会是root被PropertyOverrideConfigurer覆盖。
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 的实例
到此,相信大家对“如何理解Spring Ioc容器Bean”有了更深的了解,不妨来实际操作一番吧!这里是亿速云网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。