Java 基于xml的Spring应用
1.SpringBean 的配置解析
- Spring开发中主要是对Bean的配置,Bean的常用配置一览如下:
1.Bean的基础配置
配置UserDaoImpl由Spring容器负责管理
<bean id="userDao" class="org.example.UserDaoImpl"></bean>
此时存储到Spring容器(singleObjects单例池)中的Bean的beanName是userDao,值是UserDaoImpl对象,可以根据beanName获取Bean实例
applicationContext.getBean("userDao")
如果不配置id,则Spring会把当前Bean实例的全限定名作为beanName
public static void main(String[] args) {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");
UserDao bean = (UserDao) applicationContext.getBean("org.example.UserDaoImpl");
System.out.println(bean);
}
如果配置了id,便不能在使用Bean实例的全限定名进行获取,例如:
applicationContext.getBean("org.example.UserDaoImpl");
配置别名,配置别名后可以使用别名获得Bean对象实例
<bean id="userDao" name="aaa,bbb" class="org.example.UserDaoImpl"></bean>
2.SpringBean的配置详解
1.Bean的范围配置
默认情况下,单纯的Spring环境Bean的作用范围有两个:Singleton和Prototype
- singleton:单例,默认值,Spring容器创建的时候,就会进行Bean的实例化,并且存储到容器内部的单例池中,每次getBean时都是从单例池中获取相同的Bean实例
<bean id="userDao" class="org.example.UserDaoImpl" scope="singleton"></bean>
- prototype:原型,Spring容器初始化时不会创建Bean实例,只有调用getBean时才会实例化Bean,每次getBean都会创建一个新的Bean实例
<bean id="userDao" class="org.example.UserDaoImpl" scope="prototype"></bean>
如果是spring-webmvc的情况下,还会增加两个作用范围:request和session
maven导包
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.3.7</version>
</dependency>
- request:将创建的对象放在request域当做
<bean id="userDao" class="org.example.UserDaoImpl" scope="request"></bean>
- session:将创建的对象放在session域当做
<bean id="userDao" class="org.example.UserDaoImpl" scope="session"></bean>
2.Bean的延迟加载
当lazy-init设置为true时为延迟加载,也就是当Spring容器创建的时候,不会立即创建Bean实例,等待用到时在创建Bean实例并且存储到单例池中去,后续在使用该Bean直接冲单例池获取,本质上该Bean还是单例的,只对scope设置为singleton的Bean起作用,对prototype无效,对BeanFactory作为容器也无效
<bean id="userDao" class="org.example.UserDaoImpl" lazy-init="true"></bean>
3.Bean的初始化方法和销毁方法
- init-method:初始化时运行方法
- destroy-method:销毁时运行方法,单例模式容器必须显示关闭才会执行这个方法,否则不会执行关闭,又因为ApplicationContext的接口没有关闭容器的方法,所以类型需要使用ClassPathXmlApplicationContext,才有close显式关闭容器,如果不使用显式关闭,则有可能不会执行销毁方法,例如容器挂掉后就无法执行销毁方法
beans.xml:
<bean id="userDao" class="org.example.UserDaoImpl" init-method="init" destroy-method="destroy"></bean>
UserDaoImpl.java
public class UserDaoImpl implements UserDao{
public void init(){
System.out.println("初始化方法");
}
public void destroy(){
System.out.println("销毁方法");
}
}
主函数调用
public static void main(String[] args) {
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");
UserDao userDao = (UserDao) applicationContext.getBean("userDao");
System.out.println(userDao);
applicationContext.close();
}
结果输出
初始化方法
org.example.UserDaoImpl@7d68ef40
销毁方法
扩展:除此之外,我们还可以通过实现InitializingBean接口,完成一些Bean的初始化操作,比init-method方法优先级要高
UserDaoImpl.java
public class UserDaoImpl implements UserDao, InitializingBean {
public void init(){
System.out.println("初始化方法");
}
public void destroy(){
System.out.println("销毁方法");
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("属性执行之后进行调用");
}
}
主函数调用
public static void main(String[] args) {
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");
UserDao userDao = (UserDao) applicationContext.getBean("userDao");
System.out.println(userDao);
applicationContext.close();
}
结果输出
属性执行之后进行调用
初始化方法
org.example.UserDaoImpl@5b0abc94
销毁方法
4.Bean的实例化配置
Spring的实例化方式主要如下两种:
- 构造方式实例化:底层通过构造方法对Bean进行实例化
- 工厂方式实例化:底层通过调用自定义的工厂方法对Bean进行实例化
构造方式实例化Bean分为有参构造和无参构造方法实例化,Spring中配置的<bean>几乎都是无参构造,有参构造例子如下:
UserDaoImpl.java
public class UserDaoImpl implements UserDao {
public UserDaoImpl(String name){
System.out.println(name);
}
}
有参构造在实例化Bean时,需要参数的注入,通过constructor-arg标签,嵌入在bean标签内部提供构造参数
beans.xml
<bean id="userDao" class="org.example.UserDaoImpl">
<constructor-arg value="你好"/>
</bean>
工厂方式实例化Bean,又分为如下三种:
静态工厂方法实例化Bean
实例工厂方法实例化Bean
实现FactoryBean规范延迟实例化Bean
- 静态工厂实例化Bean:
创建一个静态方法
public class MyBeanFactory1 {
public static UserDao userDao(){
return new UserDaoImpl();
}
}
配置beans.xml文件,factory-method指定静态方法,如果有传参也需要constructor-arg进行传值
<bean id="userDao1" class="factory.MyBeanFactory1" factory-method="userDao"></bean>
主函数调用
public static void main(String[] args) {
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");
Object useDao1 = applicationContext.getBean("userDao1");
System.out.println(useDao1);
}
执行结果
org.example.UserDaoImpl@159f197
- 实例工厂方法化Bean:
创建一个方法
public class MyBeanFactory2 {
public UserDao userDao(){
return new UserDaoImpl();
}
}
beans.xml中配置该静态方法对bean,并且再次配置一个bean指向该bean,并且使用方法,如果有传参也需要constructor-arg进行传值
<!-- 配置工厂对象 -->
<bean id="myBeanFactory2" class="factory.MyBeanFactory2"></bean>
<bean id="userDao2" factory-bean="myBeanFactory2" factory-method="userDao"></bean>
主函数执行
public static void main(String[] args) {
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");
Object userDao2 = applicationContext.getBean("userDao2");
System.out.println(userDao2);
}
结果输出
org.example.UserDaoImpl@51e5fc98
- 实现FactoryBean规范延迟实例化Bean
类的接口继承于FactoryBean,在BeanFactory创建时便已经创建实例,但是实例的值并不是真实的对象本身,而是当getBean进行调用的时候,才会将实例对象新建调用getObject方法并且存放到缓存池,然后从缓存池取值从而返回实例对象,如果后续进行重复取值,不会再
创建一个新的对象,而是从缓存池取值后直接返回,从而实现FactoryBean规范延迟加载Bean
public class MyBeanFactory3 implements FactoryBean<UserDao> {
@Override
public UserDao getObject() throws Exception {
return new UserDaoImpl();
}
@Override
public Class<?> getObjectType() {
return null;
}
}
主函数调用
public static void main(String[] args) {
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");
Object userDao3 = applicationContext.getBean("userDao3");
Object userDao4 = applicationContext.getBean("userDao3");
System.out.println(userDao3);
System.out.println(userDao4);
}
运行结果
org.example.UserDaoImpl@48fa0f47
org.example.UserDaoImpl@48fa0f47
5.Bean的注入方式
其中,ref是reference的缩写,翻译为参考涉及到意思,用于引入其他Bean的id。value用于注入普通的属性值。
6.Bean的依赖注入配置
- 配置注入普通类型的List对象
配置接口
public interface UserService {
public List<String> getStringList();
}
配置实现类
public class UserServiceImpl implements UserService {
//注入List
private List<String> stringList;
public void setStringList(List<String> stringList) {
this.stringList = stringList;
}
public List<String> getStringList() {
return stringList;
}
}
配置Beans.xml文件
<bean id="userService" class="org.example.UserServiceImpl">
<property name="stringList">
<list>
<value>aaaa</value>
<value>bbbb</value>
<value>cccc</value>
<value>dddd</value>
</list>
</property>
</bean>
主函数运行
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");
UserService userService = (UserService) applicationContext.getBean("userService");
System.out.println(userService.getStringList());
运行结果
[aaaa, bbbb, cccc, dddd]
- 配置注入引用类型的List对象
UserServicelmpl.java
public List<String> getStringList() {
return stringList;
}
public void setUserDaoList(List<UserDao> userDaoList) {
this.userDaoList = userDaoList;
}
beans.xml需要配置ref或者单独创建bean
<bean id="useService1" class="org.example.UserServiceImpl">
<property name="userDaoList">
<list>
<bean class="org.example.UserDaoImpl"/>
<bean class="org.example.UserDaoImpl"/>
<bean class="org.example.UserDaoImpl"/>
<bean class="org.example.UserDaoImpl"/>
</list>
</property>
</bean>
或者
<bean id="userDao1" class="org.example.UserDaoImpl"/>
<bean id="userDao2" class="org.example.UserDaoImpl"/>
<bean id="userDao3" class="org.example.UserDaoImpl"/>
<bean id="userDao4" class="org.example.UserDaoImpl"/>
<bean id="useService1" class="org.example.UserServiceImpl">
<property name="userDaoList">
<list>
<ref bean="userDao1"/>
<ref bean="userDao2"/>
<ref bean="userDao3"/>
<ref bean="userDao4"/>
</list>
</property>
</bean>
- 配置注入引用类型的set对象
配置和List一样,在beans.xml文件中,将list标签改为set - 配置注入引用类型的map对象
配置和List一样,在beans.xml文件中,将list标签改为map,map中标签为entry,key为键名,value为键值,value-ref为引用对象
<property name="map">
<map>
<entry key="a" value="1111"/>
<entry key="b" value="2222"/>
</map>
</property>
<property name="map">
<map>
<entry key="a" value-ref="userDao1"/>
<entry key="b" value-ref="userDao2"/>
</map>
</property>
评论 (0)