(续)SSM整合之spring笔记(IOC ,:bean的作用域,bean的生命周期,bean的后置处理器)(P080—P083)

2.12、实验十一:bean的作用域

①概念

Spring 中可以通过配置 bean 标签的 scope 属性来指定 bean 的作用域范围,各取值含义参加下表:
如果是在 WebApplicationContext 环境下还会有另外两个作用域(但不常用):

②创建spring-scope.xml

 

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    
    <bean id="student" class="com.atguigu.spring.pojo.Student" >
        <property name="sid" value="1001"></property>
        <property name="sname" value="张三"></property>
    </bean>

</beans>
测试:
   @Test
    public void testScope(){
        ApplicationContext ioc = new ClassPathXmlApplicationContext("spring-scope.xml");
        Student student1 = ioc.getBean(Student.class);
        Student student2 = ioc.getBean(Student.class);
        System.out.println(student1 == student2);
    }

结果为true 所以默认为单例,

多例

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <!--
        scope:设置bean的作用域
        scope="singleton|prototype"
        singleton(单例):表示获取该bean所对应的对象都是同一个
        prototype(多例):表示获取该bean所对应的对象都不是同一个
    -->
    <bean id="student" class="com.atguigu.spring.pojo.Student" scope="prototype">
        <property name="sid" value="1001"></property>
        <property name="sname" value="张三"></property>
    </bean>

</beans>

测试:

2.13、实验十二:bean的生命周期  

①具体的生命周期过程

bean 对象创建    实例化(调用无参构造器)
bean 对象设置属性
bean 对象初始化之前操作(由 bean 的后置处理器负责)
bean 对象初始化(需在配置 bean 时指定初始化方法)
bean 对象初始化之后操作(由 bean 的后置处理器负责)
bean 对象就绪可以使用
bean 对象销毁(需在配置 bean 时指定销毁方法)
IOC 容器关闭

②新建类User

package com.atguigu.spring.pojo;

/**
 * Date:2022/7/1
 * Author:ybc
 * Description:
 */
public class User {

    private Integer id;
    private String username;
    private String password;
    private Integer age;
    public User() {
    }
    public User(Integer id, String username, String password, Integer age) {
        this.id = id;
        this.username = username;
        this.password = password;
        this.age = age;
    }
    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    public String getUsername() {
        return username;
    }
    public void setUsername(String username) {
        this.username = username;
    }
    public String getPassword() {
        return password;
    }
    public void setPassword(String password) {
        this.password = password;
    }
    public Integer getAge() {
        return age;
    }
    public void setAge(Integer age) {
        this.age = age;
    }
    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", username='" + username + '\'' +
                ", password='" + password + '\'' +
                ", age=" + age +
                '}';
    }
}

③配置bean

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="user" class="com.atguigu.spring.pojo.User" >
        
        <property name="id" value="1"></property>
        <property name="username" value="admin"></property>
        <property name="password" value="123456"></property>
        <property name="age" value="23"></property>

    </bean>
</beans>

④ . 修改类User

package com.atguigu.spring.pojo;

/**
 * Date:2022/7/1
 * Author:ybc
 * Description:
 */
public class User {

    private Integer id;

    private String username;

    private String password;

    private Integer age;

    public User() {
        System.out.println("生命周期1:实例化");
    }

    public User(Integer id, String username, String password, Integer age) {
        this.id = id;
        this.username = username;
        this.password = password;
        this.age = age;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        System.out.println("生命周期2:依赖注入");
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", username='" + username + '\'' +
                ", password='" + password + '\'' +
                ", age=" + age +
                '}';
    }

    public void initMethod(){
        System.out.println("生命周期3:初始化");
    }

    public void destroyMethod(){
        System.out.println("生命周期4:销毁");
    }

}

⑤  测试

   @Test
    public void test(){
        //ConfigurableApplicationContext是ApplicationContext的子接口,其中扩展了刷新和关闭容器的方法
      //  ConfigurableApplicationContext ioc = new ClassPathXmlApplicationContext("spring-lifecycle.xml");
        ApplicationContext ioc = new ClassPathXmlApplicationContext("spring-lifecycle.xml");
        User user = ioc.getBean(User.class);
        System.out.println(user);
    }

 要设置初始化init和销毁destroy的方法 要通过bean标签的属性来指定的

bean

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

   <!-- 使用init-method属性指定初始化方法 -->
   <!-- 使用destroy-method属性指定销毁方法 -->
 <bean id="user" class="com.atguigu.spring.pojo.User"  init-method="initMethod" destroy-method="destroyMethod">

        <property name="id" value="1"></property>
        <property name="username" value="admin"></property>
        <property name="password" value="123456"></property>
        <property name="age" value="23"></property>

    </bean>
</beans>
测试
    @Test
    public void test(){
        //ConfigurableApplicationContext是ApplicationContext的子接口,其中扩展了刷新和关闭容器的方法
      //  ConfigurableApplicationContext ioc = new ClassPathXmlApplicationContext("spring-lifecycle.xml");
        ApplicationContext ioc = new ClassPathXmlApplicationContext("spring-lifecycle.xml");
        User user = ioc.getBean(User.class);
        System.out.println(user);
    }

}

ioc的bean在什么时候销毁 是在ioc容器关闭的时候ioc.close();销毁
    @Test
    public void test(){
        //ConfigurableApplicationContext是ApplicationContext的子接口,其中扩展了刷新和关闭容器的方法
       ConfigurableApplicationContext ioc = new ClassPathXmlApplicationContext("spring-lifecycle.xml");
       // ApplicationContext ioc = new ClassPathXmlApplicationContext("spring-lifecycle.xml");
        User user = ioc.getBean(User.class);
        System.out.println(user);
        ioc.close();
    }
}

总结:

* 生命周期的步骤:
 * 1、实例化
 * 2、依赖注入
 * 3、初始化,需要通过bean的init-method属性指定初始化的方法
 * 4、IOC容器关闭时销毁,需要通过bean的destroy-method属性指定销毁的方法

⑥ bean的作用域对生命周期的影响

测试:

    @Test
    public void test(){
        //ConfigurableApplicationContext是ApplicationContext的子接口,其中扩展了刷新和关闭容器的方法
       ConfigurableApplicationContext ioc = new ClassPathXmlApplicationContext("spring-lifecycle.xml");
       // ApplicationContext ioc = new ClassPathXmlApplicationContext("spring-lifecycle.xml");
       /* User user = ioc.getBean(User.class);
        System.out.println(user);
        ioc.close();*/
    }

修改bean

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="user"  scope="prototype" class="com.atguigu.spring.pojo.User"  init-method="initMethod" destroy-method="destroyMethod">

        <property name="id" value="1"></property>
        <property name="username" value="admin"></property>
        <property name="password" value="123456"></property>
        <property name="age" value="23"></property>

    </bean>
</beans>

 测试

    @Test
    public void test(){
        //ConfigurableApplicationContext是ApplicationContext的子接口,其中扩展了刷新和关闭容器的方法
       ConfigurableApplicationContext ioc = new ClassPathXmlApplicationContext("spring-lifecycle.xml");
       // ApplicationContext ioc = new ClassPathXmlApplicationContext("spring-lifecycle.xml");
       /* User user = ioc.getBean(User.class);
        System.out.println(user);
        ioc.close();*/
    }

 结论:当我们把bean的作用域设置成多例的时候 ,因为每一次通过bean获取到的对象都是一个新的对象,没有必要ioc获取的时候就直接把对象创建好,因为是多例,所以每一次获取都是一个新对象,也就是说并不是在获取ioc容器的时候执行

在测

    @Test
    public void test(){
        //ConfigurableApplicationContext是ApplicationContext的子接口,其中扩展了刷新和关闭容器的方法
       ConfigurableApplicationContext ioc = new ClassPathXmlApplicationContext("spring-lifecycle.xml");
       // ApplicationContext ioc = new ClassPathXmlApplicationContext("spring-lifecycle.xml");
        User user = ioc.getBean(User.class);
        System.out.println(user);
        ioc.close();
    }

总结:

如果是多例,前三个步骤是在获取bean的时候执行 不是获取ioc容器的时候执行,设置成多例后,每一次通过bean来获取的对象都是一个新的对象,所以没有必要提前创建

问题 :当把容器关闭后 销毁并没有执行

当我们把bean的作用域设置成多例的时候,销毁的方法不由我们的ioc容器管理了(了解)

⑦  bean的后置处理器

bean 的后置处理器会在生命周期的初始化前后添加额外的操作,需要实现 BeanPostProcessor 接口, 且配置到IOC 容器中,需要注意的是, bean 后置处理器不是单独针对某一个 bean 生效,而是针对 IOC 容 器中所有bean 都会执行

创建bean的后置处理器: process.MyBeanPostProcessor

ctrl+O   重写方法

 

MyBeanPostProcessor
public class MyBeanPostProcessor implements BeanPostProcessor {


    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        //此方法在bean的生命周期初始化之前执行
        System.out.println("MyBeanPostProcessor-->后置处理器postProcessBeforeInitialization");
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        //此方法在bean的生命周期初始化之后执行
        System.out.println("MyBeanPostProcessor-->后置处理器postProcessAfterInitialization");
        return bean;
    }
}

IOC容器中配置后置处理器:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="user"  class="com.atguigu.spring.pojo.User"  init-method="initMethod" destroy-method="destroyMethod">

        <property name="id" value="1"></property>
        <property name="username" value="admin"></property>
        <property name="password" value="123456"></property>
        <property name="age" value="23"></property>
    </bean>

    <bean id="myBeanPostProcessor" class="com.atguigu.spring.process.MyBeanPostProcessor"></bean>
</beans>

 测试

    @Test
    public void test(){
        //ConfigurableApplicationContext是ApplicationContext的子接口,其中扩展了刷新和关闭容器的方法
       ConfigurableApplicationContext ioc = new ClassPathXmlApplicationContext("spring-lifecycle.xml");
       // ApplicationContext ioc = new ClassPathXmlApplicationContext("spring-lifecycle.xml");
        User user = ioc.getBean(User.class);
        System.out.println(user);
        ioc.close();
    }

 总结:

/**
     具体的生命周期过程
 * 1、实例化
 * 2、依赖注入
 * 3、后置处理器的postProcessBeforeInitialization
 * 4、初始化,需要通过bean的init-method属性指定初始化的方法
 * 5、后置处理器的postProcessAfterInitialization
 * 6、IOC容器关闭时销毁,需要通过bean的destroy-method属性指定销毁的方法
 *
 * bean的后置处理器会在生命周期的初始化前后添加额外的操作
 * 需要实现BeanPostProcessor接口且配置到IOC容器中
 * 需要注意的是,bean后置处理器不是单独针对某一个bean生效,而是针对IOC容器中所有bean都会执行
 *
 * 注意:
 * 若bean的作用域为单例时,生命周期的前三个步骤会在获取IOC容器时执行
 * 若bean的作用域为多例时,生命周期的前三个步骤会在获取bean时执行
 */

2.14、实验十三:FactoryBean

①简介
FactoryBean Spring 提供的一种整合第三方框架的常用机制。和普通的 bean 不同,配置一个
FactoryBean 类型的 bean ,在获取 bean 的时候得到的并不是 class 属性中配置的这个类的对象,而是 getObject()方法的返回值。通过这种机制, Spring 可以帮我们把复杂组件创建的详细过程和繁琐细节都屏蔽起来,只把最简洁的使用界面展示给我们。
将来我们整合 Mybatis 时, Spring 就是通过 FactoryBean 机制来帮我们创建 SqlSessionFactory 对象的。
package org.springframework.beans.factory;
import org.springframework.lang.Nullable;


//<T>工厂所提供的类型
public interface FactoryBean<T> {
String OBJECT_TYPE_ATTRIBUTE = "factoryBeanObjectType";

//获取对象
@Nullable
T getObject() throws Exception;

//获取对象的类型
@Nullable
Class<?> getObjectType();

//是否单例
default boolean isSingleton() {
return true;
}
}

②创建类UserFactoryBean

ctrl+i 重写

package com.atguigu.spring.factory;

import com.atguigu.spring.pojo.User;
import org.springframework.beans.factory.FactoryBean;

/**
 * Date:2022/7/1
 * Author:ybc
 * Description:
 * FactoryBean是一个接口,需要创建一个类实现该接口
 * 其中有三个方法:
 * getObject():通过一个对象交给IOC容器管理
 * getObjectType():设置所提供对象的类型
 * isSingleton():所提供的对象是否单例
 * 当把FactoryBean的实现类配置为bean时,会将当前类中getObject()所返回的对象交给IOC容器管理
 *
 */
public class UserFactoryBean implements FactoryBean<User> {
    @Override
    public User getObject() throws Exception {
        return new User();
    }

    @Override
    public Class<?> getObjectType() {
        return User.class;
    }
}

③配置bean

spring-factory.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
  
    <bean class="com.atguigu.spring.factory.UserFactoryBean"></bean>
    
</beans>

 把UserFactoryBean里面getObject()方法的所返回的对象 return new User();交给IOC容器

真正交给IOC管理的是UserFactoryBean里面getObject()方法里面User的bean

测试: FactoryBeanTest

public class FactoryBeanTest {

    @Test
    public void testFactoryBean(){
             //获取IOC容器
        ApplicationContext ioc = new ClassPathXmlApplicationContext("spring-factory.xml");
        User user = ioc.getBean(User.class);
        System.out.println(user);
    }

}

我们把FactoryBean配置到IOC容器中,并不是把UserFactoryBean这个类型交给IOC容器管理,而是把UserFactoryBean类型中的getObject()方法的返回值交给IOC容器管理

 FactoryBean和普通工厂的区别:(以后在整理 现在有点乱)

总结:

* FactoryBean是一个接口,需要创建一个类实现该接口
* 其中有三个方法:
* getObject():通过一个对象交给IOC容器管理
* getObjectType():设置所提供对象的类型
* isSingleton():所提供的对象是否单例
* 当把FactoryBean的实现类配置为bean时,会将当前类中getObject()所返回的对象交给IOC容器管理

拓展:

一.FactoryBean和普通Bean的区别

Spring 中有两种类型的Bean:一种是普通Bean,另一种是工厂Bean 即 FactoryBean。
FactoryBean跟普通Bean不同,其返回的对象不是指定类的一个实例,而是该FactoryBean的getObject方法所返回的对象。创建出来的对象是否属于单例由isSingleton中的返回决定。

二 .spring中FactoryBean和BeanFactory的区别

1 .BeanFactory

BeanFactory,以Factory结尾,表示它是一个工厂类(接口), 它负责生产和管理bean的一个工厂,我们可以通过它获取工厂管理的对象。在Spring中,BeanFactory是IOC容器的核心接口,它的职责包括:实例化、定位、配置应用程序中的对象及建立这些对象间的依赖。它定义了getBean()、containsBean()等管理Bean的通用方法。但BeanFactory只是个接口,并不是IOC容器的具体实现,但是Spring容器给出了很多种实现,如 :

DefaultListableBeanFactory
XmlBeanFactory
ApplicationContext

其中XmlBeanFactory就是常用的一个,该实现将以XML方式描述组成应用的对象及对象间的依赖关系。

源码:

public interface BeanFactory {
    /**
    用于区分factoryBean和bean,后面会讲到
    /*String FACTORY_BEAN_PREFIX = "&";
    /**
     返回byName返回bean的实例
    */
    Object getBean(String name) throws BeansException;
 
    <T> T getBean(String name, Class<T> requiredType) throws BeansException;
 
    Object getBean(String name, Object... args) throws BeansException;
 
    <T> T getBean(Class<T> requiredType) throws BeansException;
 
    <T> T getBean(Class<T> requiredType, Object... args) throws BeansException;
 
    <T> ObjectProvider<T> getBeanProvider(Class<T> requiredType);
 
    <T> ObjectProvider<T> getBeanProvider(ResolvableType requiredType);

    /**
     判断工厂中是否包含给定名称的bean定义,若有则返回true
    */
    boolean containsBean(String name);
 
    /**
    判断bean是否为单例
    */
    boolean isSingleton(String name) throws NoSuchBeanDefinitionException;
 
    /**
    判断bean是否为多例
    */
    boolean isPrototype(String name) throws NoSuchBeanDefinitionException;
 
    /**
    检查具有给定名称的bean是否匹配指定的类型。
     */
    boolean isTypeMatch(String name, ResolvableType typeToMatch) throws NoSuchBeanDefinitionException;
    boolean isTypeMatch(String name, Class<?> typeToMatch) throws NoSuchBeanDefinitionException;
    /**
    返回给定名称的bean的Class,如果没有找到指定的bean实例,则排除*/
    @Nullable
    Class<?> getType(String name) throws NoSuchBeanDefinitionException;
    /**
    返回给定bean名称的所有别名 
    */
    String[] getAliases(String name);
}
使用场景

从Ioc容器中获取Bean(byName or byType)
检索Ioc容器中是否包含指定的Bean
判断Bean是否为单例

2 .FactoryBean

使用XML配置spring容器的时候,Spring通过反射机制利用<bean>的class属性指定实现类实例化Bean,在某些情况下,实例化Bean过程比较复杂,如果按照传统的方式,则需要在<bean>中提供大量的配置信息。配置方式的灵活性是受限的,比如一个类大量依赖了其他的对象属性,此时就算是使用自动装配,不需要再显式的写出bean之间的依赖关系,但是其依赖的对象也需要将其装配到spring容器中,也需要为它所依赖的多有对象都创建bean标签将他们注入,如果这个类依赖了上百个对象,那么这个工作量无疑是非常大的。

Spring为此提供了一个org.springframework.bean.factory.FactoryBean的工厂类接口,用户可以通过实现该接口定制实例化Bean的逻辑。FactoryBean接口对于Spring框架来说占用重要的地位,Spring自身就提供了70多个FactoryBean的实现。它们隐藏了实例化一些复杂Bean的细节,给上层应用带来了便利。从Spring3.0开始,FactoryBean开始支持泛型,即接口声明改为FactoryBean<T>的形式。

Spring中共有两种bean,一种为普通bean,另一种则为工厂bean

以Bean结尾,表示它是一个Bean,不同于普通Bean的是:它是实现了FactoryBean<T>接口的Bean,根据该Bean的ID从BeanFactory中获取的实际上是FactoryBean的getObject()返回的对象,而不是FactoryBean本身,如果要获取FactoryBean对象,请在id前面加一个&符号来获取。
源码:

public interface FactoryBean<T> {
    //从工厂中获取bean
    @Nullable
    T getObject() throws Exception;
 
    //获取Bean工厂创建的对象的类型
    @Nullable
    Class<?> getObjectType();
 
    //Bean工厂创建的对象是否是单例模式
    default boolean isSingleton() {
        return true;
    }
}

从它定义的接口可以看出,FactoryBean表现的是一个工厂的职责。 即一个Bean A如果实现了FactoryBean接口,那么A就变成了一个工厂,根据A的名称获取到的实际上是工厂调用getObject()返回的对象,而不是A本身,如果要获取工厂A自身的实例,那么需要在名称前面加上'&'符号。

getObject('name')返回工厂中的实例
getObject('&name')返回工厂本身的实例

区别:

BeanFactory 以Factory结尾,表示它是一个工厂类,用于管理Bean的一个工厂。在Spring中,所有的Bean都是由BeanFactory(也就是IOC容器)来进行管理的。该接口是IoC容器的顶级接口,是IoC容器的最基础实现,也是访问Spring容器的根接口,负责对bean的创建,访问等工作
对FactoryBean而言,以Bean结尾,说明这是一个交给容器去管理的bean。这个Bean不是简单的Bean,而是一个能生产或者修饰对象生成的工厂Bean,它的实现与设计模式中的工厂模式和修饰器模式类似。


三 . 理解Spring中ApplicationContext和BeanFactory以及FactoryBean

1.BeanFactroy采用的是延迟加载形式来注入Bean的,即只有在使用到某个Bean时(调用getBean()),才对该Bean进行加载实例化,这样,我们就不能发现一些存在的Spring的配置问题。而ApplicationContext则相反,它是在容器启动时,一次性创建了所有的Bean。这样,在容器启动时,我们就可以发现Spring中存在的配置错误。 相对于基本BeanFactory,ApplicationContext 唯一的不足是占用内存空间。当应用程序配置Bean较多时,程序启动较慢。

BeanFacotry延迟加载,如果Bean的某一个属性没有注入,BeanFacotry加载后,直至第一次使用调用getBean方法才会抛出异常;而ApplicationContext则在初始化自身是检验,这样有利于检查所依赖属性是否注入;所以通常情况下我们选择使用 ApplicationContext。
应用上下文则会在上下文启动后预载入所有的单实例Bean。通过预载入单实例bean ,确保当你需要的时候,你就不用等待,因为它们已经创建好了。

2.BeanFactory和ApplicationContext都支持BeanPostProcessor,BeanFactoryPostProcessor的使用,但两者之间的区别是:BeanFactory需要手动注册,而ApplicationContext则是自动注册。(Applicationcontext比 beanFactory 加入了一些更好使用的功能。而且 beanFactory 的许多功能需要通过编程实现而 Applicationcontext 可以通过配置实现。比如后处理 bean , Applicationcontext 直接配置在配置文件即可而 beanFactory 这要在代码中显示的写出来才可以被容器识别。 )

3.beanFactory主要是面对与 spring 框架的基础设施,面对 spring 自己。而 Applicationcontex 主要面对与 spring 使用的开发者。基本都会使用 Applicationcontex 并非 beanFactory 。

4. BeanFactory是个bean 工厂,是一个工厂类(接口), 它负责生产和管理bean的一个工厂
是ioc 容器最底层的接口,是个ioc容器,是spring用来管理和装配普通bean的ioc容器(这些bean成为普通bean)。FactoryBean是个bean,在IOC容器的基础上给Bean的实现加上了一个简单工厂模式和装饰模式,是一个可以生产对象和装饰对象的工厂bean,由spring管理后,生产的对象是由getObject()方法决定的。
 


 

 
     

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值