spring6-工厂设计模式与bean的实例化方式

bean的作用域

ioc容器默认bean是单例的(singleton)。

bean对象的创建是在初始化上下文的时候就创建了,每一次调用getBean()时,都返回那个单例对象。

java 复制代码
// 这行代码会创建配置里面的bean对象
ApplicationContext context = new FileSystemXmlApplicationContext("D:/applicationContext.xml");

那如何把bean设置成多例的?

xml 复制代码
<!--    scope="prototype" 会使这个bean变成多例的-->
<bean id="sb" class="com.ali.bean.SpringBean"  scope="prototype"/>
java 复制代码
// 由于这个bean是多例模式,这行代码不会创建bean对象。而是在调用getBean()时创建对象
ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml","spring-dao.xml");
// 这行代码才会创建bean对象
Object user=  context.getBean("sb");
xml 复制代码
<!--    scope="prototype" 会使这个bean变成多例的
        目前scope有2个值:singleton 和 prototype
        当项目引入spring-webmvc依赖变成web项目时,scope会多2个属性
        request:表示每次http请求都会创建一个新的bean对象
        session: 表示每次 session都会创建一个新的bean对象
-->
    <bean id="sb" class="com.ali.bean.SpringBean"  scope="prototype"/>

自定义scope

  1. 自定义Scope(实现Scope接口)

    • spring内置了线程范围类: org.springframework.context.support.SimpleThreadScope
  2. 添加配置信息

xml 复制代码
    <bean id="sb" class="com.ali.bean.SpringBean"  scope="threadScope"/>

<!--    配置自定义的作用域,实现一个线程一个bean-->
    <bean class="org.springframework.beans.factory.config.CustomScopeConfigurer" >
        <property name="scopes">
            <map>
                <entry key="threadScope">
<!--                    这个SimpleThreadScope 是spring框架内置的,也可以自定义-->
                    <bean class="org.springframework.context.support.SimpleThreadScope"></bean>
                </entry>
            </map>
        </property>
    </bean>

GoF之工厂模式

工厂模式的三种形态

  1. 简单工厂模式(Simple Factory):又叫静态工厂方法模式。是工厂方法模式的一种特殊实现。
  2. 工厂方法模式 (Factory Method)
  3. 抽象工厂模式 (Abstract Factory)

简单工厂模式

简单工厂模式包括三个角色:抽象产品、具体产品、工厂类。代码如下:

  1. 抽象产品类
java 复制代码
// 抽象产品角色
public abstract class Weapon {
	public abstract void attack();
}
  1. 具体产品

    java 复制代码
    // 具体产品角色:匕首
    public class Dagger extends Weapon{
        @Override
        public void attack() {
            System.out.println("匕首攻击...");
        }
    }
java 复制代码
// 具体产品角色:战斗机
public class Fighter extends Weapon{
    @Override
    public void attack() {
        System.out.println("战斗机攻击...");
    }
}
java 复制代码
// 具体产品角色:坦克
public class Tank extends Weapon{
    @Override
    public void attack() {
      System.out.println( "坦克攻击。。。");
    }
}
  1. 工厂类角色
java 复制代码
// 工厂类角色
public class WeaponFactory {
    /**
     * 静态方法:根据传入的参数获取相应的武器
     * @return
     */
    public static Weapon get(String type){
        switch (type){
            case "Tank":
                return new Tank();
            case "Fighter":
                return new Fighter();
            case "Dagger":
                return new Dagger();
            default:
                return null;
        }
    }
}

测试代码:

java 复制代码
public class Main {
    public static void main(String[] args) {
        // 简单工厂模式达到职责分离。客户端不关心产品生产的细节
        // 客户端只负责消费,工厂类负责生产。这就是简单工厂模式的作用。
        Weapon weapon1 = WeaponFactory.get("Tank");
        weapon1.attack();
        Weapon weapon2 = WeaponFactory.get("Fighter");
        weapon2.attack();
        Weapon weapon3 = WeaponFactory.get("Dagger");
        weapon3.attack();
    }
}

优缺点:

优点:实现职责分离。

缺点:假如要添加新产品。需要修改工厂类代码。显然违反了ocp原则。

​ 工厂类责任重大。一旦瘫痪,这个系统必然瘫痪。

工厂方法模式

工厂方法模式保留了简单工厂模式的优点。同时解决了简单工厂模式的缺点。

解决方法是:一个工厂对应一个产品。符合ocp原则。

优点:扩展性高。要想增加一个产品。只要扩展一个工厂类就可以。

复制代码
	屏蔽产品具体实现。调用者只关心产品的接口。

缺点:会使类的数量成倍增加,增加系统复杂度。

工厂方法模式的角色包括:

  • 抽象工厂角色
  • 具体工厂角色
  • 抽象产品角色
  • 具体产品角色

代码如下:

java 复制代码
// 抽象产品角色
public abstract class Weapon {
    public abstract void attack();
}

// 具体产品角色:匕首
public class Dagger extends Weapon {
    @Override
    public void attack() {
        System.out.println("匕首攻击...");
    }
}

// 具体工厂类:枪械工厂
public class GunFactory extends WeaponFactory{
    @Override
    public Weapon get() {
        return new Gun();
    }
}

// 抽象工厂类
public abstract class WeaponFactory {

    public abstract Weapon get();
}

// 具体工厂类:匕首工厂
public class DaggerFactory extends WeaponFactory{
    @Override
    public Weapon get() {
        return new Dagger();
    }
}

// 具体工厂类:枪械工厂
public class GunFactory extends WeaponFactory{
    @Override
    public Weapon get() {
        return new Gun();
    }
}

测试代码:

java 复制代码
public static void main(String[] args) {
    WeaponFactory weaponFactory = new DaggerFactory();
    Weapon dagger = weaponFactory.get();
    dagger.attack();

    WeaponFactory weaponFactory1 = new GunFactory();
    Weapon gun = weaponFactory1.get();
    gun.attack();
}

bean的实例化

spring为bean提供了多种实例化的方式,通常包括4种方式。

  1. 通过构造方法实例化
  2. 通过简单工厂模式实例化
  3. 通过factory-bean实例化
  4. 通过FactoryBean接口实例化

通过构造方法实例化

xml 复制代码
<!--    spring会自动调用该类的无参数构造方法来实例化对象,这个SpringBean类必须有一个无参数的构造方法-->
    <bean id="springBean" class="com.ali.bean.SpringBean" />

通过简单工厂模式实例化

java 复制代码
// 工厂类
public class StarFactory {
    public static Star createStar() {
        return new Star();
    }
}
xml 复制代码
<!--    静态(简单)工厂方法实例化bean 指定调用哪个类的哪个方法。这里实例化的是Star对象。
      factory-method 指定的是工厂类中的静态方法名称。
-->
  <bean id="starBean" class="com.ali.bean.StarFactory" factory-method="createStar"></bean>

通过factory-bean实例化

java 复制代码
// 工厂方法模式中的具体产品类
public class Gun {
    public Gun() {
        System.out.println("无参数构造器:Gun()");
    }
}

// 工厂方法模式中的具体工厂类
public class GunFactory {
    public Gun get(){
        return new Gun();
    }
}
xml 复制代码
<!--    通过工厂方法模式实例化bean。由factory-bean指定工厂类的bean id,factory-method指定工厂类中的实例方法名称-->
    <bean id="gunFactory" class="com.ali.bean.GunFactory"></bean>
    <bean id="gun" factory-bean="gunFactory" factory-method="get"></bean>

通过FactoryBean接口实例化

通过factory-bean实例化的方式需要我们自定义factory-bean和factory-method。

在spring中,当自己的类实现了FactoryBean接口后factory-bean和factory-method就不需要指定了。factory-bean会自动指向实现FactoryBean接口的类,factory-method会自动指向getObject()方法。

java 复制代码
public class PersonFactoryBean implements FactoryBean<Person> {
    @Override
    public Person getObject() throws Exception {
        // 手动创建对象
        return new Person();
    }

    @Override
    public Class<?> getObjectType() {
        return null;
    }

}
xml 复制代码
<!--PersonFactoryBean实现了FactoryBean接口,Spring会调用它的getObject方法来实例化person对象
不用写factory-bean和factory-method,直接将PersonFactoryBean配置为一个普通的bean即可
 这样spring会自动调用PersonFactoryBean的getObject方法来实例化person对象-->
<bean id="person" class="com.ali.bean.PersonFactoryBean"></bean>

BeanFactory和FactoryBean的区别

BeanFactory:spring ioc容器的顶级对象,负责创建bean对象。BeanFactory是工厂

FactoryBean:本质是一个bean。能够辅助spring实例化其他bean对象。

相关推荐
她说..3 小时前
策略模式+工厂模式实现审批流(面试问答版)
java·后端·spring·面试·springboot·策略模式·javaee
tb_first3 小时前
SSM速通4
java·jvm·spring·tomcat·maven·mybatis
人道领域5 小时前
javaWeb从入门到进阶(maven高级进阶)
java·spring·maven
qq_12498707536 小时前
基于springboot的尿毒症健康管理系统的设计与实现(源码+论文+部署+安装)
java·spring boot·spring·毕业设计·计算机毕业设计
lynnlovemin10 小时前
云原生提速秘籍:Spring Boot转Spring Native实战指南
spring boot·spring·云原生·spring native
爱敲代码的憨仔10 小时前
Spring-AOP
java·后端·spring
手握风云-11 小时前
JavaEE 进阶第十五期:Spring 日志的笔墨艺术
java·spring·java-ee
知识即是力量ol11 小时前
一次完整的 Spring Security JWT 鉴权链路解析
java·后端·spring·鉴权·springsecurity
铁蛋AI编程实战11 小时前
Agentic AI/GPT-4o替代/Spring AI 2.0/国产大模型轻量化
java·人工智能·spring