详解Spring Bean的配置方式与实例化

作者:倔强的牛角 时间:2022-01-13 05:47:51 

一、 Spring Bean 配置方式

由 Spring IoC 容器管理的对象称为 Bean,Bean 配置方式有两种:配置文件开发注解开发

配置文件开发

Spring 配置文件支持两种格式:xml和properties,此教程以xml配置文件讲解。

XML 配置文件的根元素是 <beans>,该元素包含了多个子元素 <bean>。每一个 <bean> 元素都定义了一个 Bean

详解Spring Bean的配置方式与实例化

XML 配置文件常用元素表

属性名称描述
idBean 的唯一标识符,Spring IoC 容器对 Bean 的配置和管理都通过该属性完成。
nameBean 的别名,可以通过 name 属性为同一个 Bean 同时指定多个名称,每个名称之间用逗号或分号隔开。
class指定了Bean 的具体实现类,它必须是一个类的全限定名。
scopeBean 的作用域,属性值可以为 singleton(单例)、prototype(原型)、request、session 和 global Session。默认值是 singleton。

注解开发

先插个眼在这,过几天会发一篇文章详细介绍

二、Spring Bean实例化

通过控制反转,对象的创建权就交给了IoC容器,但是容器是如何来创建对象的呢?

bean本质上就是对象,对象在new的时候会使用构造方法,创建bean其实也是使用构造方法完成的。

实例化bean的三种方式:构造方法,静态工厂和实例工厂

环境准备

1.准备一个UserDao接口和一个UserDaoImpl实现类

//UserDao接口
public interface UserDao {
   public void say();
}
//UserDaoImpl实现类
public class UserDaoImpl implements UserDao {
   @Override
   public void say() {
       System.out.println("Hello,I am BigHorn!");
   }
}

2.编写spring配置文件

<bean id="userDao" class="com.bighorn.dao.impl.UserDaoImpl"/>

3.编写运行程序

public class App {
   public static void main(String[] args) {
       //获取IoC容器
       ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
       //从容器中获取对象
       UserDaoImpl userDao = context.getBean("userDao", UserDaoImpl.class);
       userDao.say();
   }
}

构造方法实例化Bean

第一种实例化bean的方法:构造方法实例化,这也是最常用的方法,因为类都会提供默认的构造方法。下面来测试下

1.在UserDaoImpl类中添加一个无参构造方法,并打印一句话,方便观察结果。

public class UserDaoImpl implements UserDao {
   //添加一个无参构造方法
   public UserDaoImpl() {
       System.out.println("这是UserDaoImpl的无参构造方法");
   }

@Override
   public void say() {
       System.out.println("Hello,I am BigHorn!");
   }
}

可以在控制台看到输出结果,说明Spring IoC 容器创建对象时用的也是构造方法

详解Spring Bean的配置方式与实例化

2.将构造方法改成private测试

public class UserDaoImpl implements UserDao {
   //将构造方法改成private
   private UserDaoImpl() {
       System.out.println("这是UserDaoImpl的无参构造方法");
   }

@Override
   public void say() {
       System.out.println("Hello,I am BigHorn!");
   }
}

发现还可以运行成功,这说明Spring底层用的是反射,访问到类中的私有构造方法。

详解Spring Bean的配置方式与实例化

3.将无参构造方法换成有参构造方法

public class UserDaoImpl implements UserDao {
   //将无参构造方法换成有参构造方法
   private UserDaoImpl(int i) {
       System.out.println("这是UserDaoImpl的无参构造方法");
   }
   @Override
   public void say() {
       System.out.println("Hello,I am BigHorn!");
   }
}

程序会报java.lang.NoSuchMethodException错,说明Spring底层使用的是类的无参构造方法

详解Spring Bean的配置方式与实例化

4.画个图总结下:Spring 配置文件中 bean 标签的 id 和类的全限定名一一对应,所以 Spring IoC容器的 getBean 方法其实就是先根据 bean 的 id 获取该类的全限定名,然后再利用反射根据类的全限定名创建对象并返回。

详解Spring Bean的配置方式与实例化

静态工厂实例化Bean

第二种实例化Bean的方法:静态工厂实例化

了解即可,一般是用来兼容早期的一些老系统。

1.创建一个UserDaoFactory工厂类并提供一个静态方法

//UserDao接口
public interface UserDao {
   public void say();
}
//UserDaoImpl实现类
public class UserDaoImpl implements UserDao {
   public UserDaoImpl() {
       System.out.println("这是UserDaoImpl的无参构造方法");
   }
   @Override
   public void say() {
       System.out.println("Hello,I am BigHorn!");
   }
}
//UserDaoFactory工厂类
public class UserDaoFactory {
   //静态工厂创建对象
   public static UserDao getUserDao(){
       System.out.println("这是静态工厂实例化Bean");
       return new UserDaoImpl();
   }
}

2.编写spring配置文件

<!--
       class:工厂类全类名
       factory-method:工厂创建对象的方法名
    -->
<bean id="userDao" class="com.bighorn.factory.UserDaoFactory" factory-method="getUserDao"/>

3.编写运行程序

public class App {
   public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
       //获取IoC容器
       ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
       //从容器中获取对象
       UserDaoImpl userDao = context.getBean("userDao", UserDaoImpl.class);
       userDao.say();
   }
}

看见运行结果,输出以下语句

详解Spring Bean的配置方式与实例化

实例工厂实例化Bean

第二种实例化Bean的方法:实例工厂实例化

了解即可,其实和静态工厂差不多。只不过静态工厂可以直接通过静态方法创建bean,实例工厂要先new一个实例工厂对象,然后再通过这个实例工厂对象创建bean

1.创建一个UserDaoFactory工厂类,和静态工厂不一样的是,实力工厂提供的是一个普通方法

//UserDaoFactory工厂类
public class UserDaoFactory {
   //实例工厂创建对象
   public  UserDao getUserDao(){
       System.out.println("这是实例工厂实例化Bean");
       return new UserDaoImpl();
   }
}

2.编写spring配置文件

<!--
        userFactory:工厂的实例对象
        factory-bean:指向工厂的实例对象
        factory-method:工厂对象中创建对象的方法名
   -->
<bean id="userFactory" class="com.bighorn.factory.UserDaoFactory"/>
<bean id="userDao" factory-bean="userFactory" factory-method="getUserDao"/>

3.运行程序和静态工厂一样,查看运行结果

详解Spring Bean的配置方式与实例化

FactoryBean

实例工厂的方法听麻烦的,其实spring框架为我们一种实例工厂的方式:FactoryBean,比较实用,用来整合其他框架

我们只需要实现FactoryBean接口即可简化开发,下面来介绍下它的具体使用方法

1.创建UserDaoFactoryBean类,实现FactoryBean接口中的三个方法:

  • boolean isSingleton():设置bean作用域,默认true表示单例,false表示非单例

  • T getObject() throws Exception:返回的是bean实例对象

  • Class<?> getObjectType():返回的是被创建类的Class对象

public class UserDaoFactoryBean implements FactoryBean<UserDao> {
   //bean作用域:默认true表示单例
   public boolean isSingleton() {
       return true;
   }
   //代替实例工厂中创建对象的方法
   public UserDao getObject() throws Exception {
       System.out.println("这是FactoryBean实例化bean");
       return new UserDaoImpl();
   }
   //返回所创建类的Class对象
   public Class<?> getObjectType() {
       return UserDao.class;
   }
}

2.编写spring配置文件

<bean id="userDao" class="com.bighorn.factory.UserDaoFactoryBean"/>

3.编写运行程序

public class App {
   public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
       //获取IoC容器
       ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
       //从容器中获取对象
       UserDaoImpl userDao1 = context.getBean("userDao", UserDaoImpl.class);
       UserDaoImpl userDao2 = context.getBean("userDao", UserDaoImpl.class);
       System.out.println(userDao1);
       System.out.println(userDao2);
   }
}

详解Spring Bean的配置方式与实例化

来源:https://juejin.cn/post/7102062596802478087

标签:Spring,Bean,配置方式,实例化
0
投稿

猜你喜欢

  • Android在项目中接入腾讯TBS浏览器WebView的教程与注意的地方

    2021-12-18 01:58:28
  • Springboot 多租户SaaS搭建方案

    2022-06-04 00:23:32
  • c#在excel中添加超链接示例分享

    2023-06-03 14:10:45
  • Room Kotlin API的使用入门教程

    2023-11-07 07:06:35
  • Android设计模式之Builder模式详解

    2022-01-17 12:29:02
  • C# Math中常用数学运算的示例详解

    2023-10-06 23:06:28
  • Android实现动态定值范围效果的控件

    2023-10-15 02:00:37
  • Java Servlet3.0异步处理问题

    2023-08-12 00:52:05
  • maven下载jar包改用阿里云maven库的方法

    2023-02-13 07:41:58
  • SpringBoot启动自动终止也不报错的原因及解决

    2023-01-16 02:15:40
  • C# winfrom 模拟ftp文件管理实现代码

    2023-07-15 16:29:48
  • Spring StopWatch使用实例详解

    2022-03-31 02:46:57
  • 深入分析Android ViewStub的应用详解

    2022-09-14 16:50:19
  • 盘点MQ中的异常测试

    2022-05-06 07:39:24
  • SpringBoot使用Redis实现分布式锁

    2021-11-06 20:10:22
  • Android开发中记一个SwipeMenuListView侧滑删除错乱的Bug

    2021-08-02 04:24:21
  • webuploader 实现图片批量上传功能附实例代码

    2022-12-03 09:13:34
  • SpringBoot定制三种错误页面及错误数据方法示例

    2022-03-10 01:15:55
  • C#控制台实现飞行棋游戏

    2022-03-12 04:18:40
  • 判断List和Map是否相等并合并List中相同的Map

    2022-12-29 02:11:10
  • asp之家 软件编程 m.aspxhome.com