Java 基于xml的Spring应用

1585364631
2023-02-22 / 0 评论 / 109 阅读 / 正在检测是否收录...

Java 基于xml的Spring应用

1.SpringBean 的配置解析

  • Spring开发中主要是对Bean的配置,Bean的常用配置一览如下:
    SpringBean xml配置

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的注入方式

Bean的注入方式
其中,ref是reference的缩写,翻译为参考涉及到意思,用于引入其他Bean的id。value用于注入普通的属性值。

6.Bean的依赖注入配置

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

评论 (0)

取消