• spring_bean三种装配方式


    bean的装配

    bean装配:spring ioc 容器将bean对象创建好并传递给使用者的过程叫bean的装配

    spring ioc 会创建我们在配置文件中配置好的对象,并将对象返回给使用者,spring ioc创建对象的方式有以下三种  

      1:默认方式,通过构造器来创建

    <bean id="自定义id" class="接口的实现类" />

      2:实例工厂

    <bean id="factory" class="工厂类" />
    <bean id="自定义id" factory-bean="factory" factory-method="调用的实例化工厂方法" />

      3:静态工厂

    <bean id="自定义id" class="工厂类" factory-method="静态工厂方法" />

    # 默认方式

    该方式spring ioc容器会调用bean(接口实现类)的无参构造方法来创建对象,当创建一个java类后,系统会自动在类中创默认构造函数,当自己创建个构造方法时默认构造函数就会不存在,所以开发者需确保在bean中存在无参构造方法

    <!-- 默认方式 -->
    <bean id="studentService" class="com.doaoao.impl.StudentServiceImpl"/>

    # 实例工厂

    1:定义一个工厂类,该类中的方法都是非静态的(方法的返回值为StudentService类型)

    package com.doaoao.factory;
    import com.doaoao.impl.StudentServiceImpl;
    import com.doaoao.service.StudentService;
    public class BeanFactory {
        public StudentService createStudentService(){
            return new StudentServiceImpl();
        }
    }

    2:修改配置文件中的内容(主要为了告诉spirng我们要使用 实例工厂 方法)

    <!-- 创建实例工厂配置温江 id 和class  -->
    <bean id="myFactory" class="com.doaoao.factory.BeanFactory" />
    
    <!-- 将上创建的实例工厂 myFactory添加进去,利用实例工厂中的方法 factory-method指定的方法,来创建studentService -->
    <bean id="studentService" factory-bean="myFactory" factory-method="createStudentService" />

    其它与之前的相同

    # 静态工厂(中的方法都是 static 修饰的)

    1:定义一个工厂类,类的中的方法都为静态方法(从该类中来看和实例工厂对比只是多了一个static)

    package com.doaoao.factory;
    import com.doaoao.impl.StudentServiceImpl;
    import com.doaoao.service.StudentService;
    public class StaticBeanFactory {
        public static StudentService createStudentService(){
            return new StudentServiceImpl();
        }
    }

    2:修改配置文件中的内容

    <!-- 静态工厂:调用class指定的工厂类的方法 createStudentService 来创建 id 指定的对象-->
    <bean id="studentService" class="com.doaoao.factory.StaticBeanFactory" factory-method="createStudentService" />

    ## 注:在使用时,一般使用默认方式即可


     ## bean的作用域

      singleton: 单例模式。即在一个Spring ioc容器中,只创建一个对象,默认为单例模式

      prototype: 原型模式。即每次使用 getBean 方法获取的同一个bean的实例都是一个新的实例

      request:对于每次 HTTP 请求,都将会产生一个不同的 Bean 实例

      session:对于每个不同的 HTTP session,都将产生一个不同的 Bean 实例(同一个浏览器中产生同一个session)

      application:在一个web应用中会产生一个bean实例,就相当于在一个ServletContext中只有该bean的实例

      websocket:在一个websocket中会产生一个bean实例

    单利模式例子:

    1:在StudetnServiceImpl.java中创建一个无参构造方法

    package com.doaoao.impl;
    import com.doaoao.service.StudentService;
    public class StudentServiceImpl implements StudentService {
        @Override
        public void testDao() {
            System.out.println("Hello World");
        }
        public StudentServiceImpl(){
            System.out.println("执行 StudentService的构造方法");
        }
    }

    2:在测试类中创建两个对象,分别执行两个对象,看输出

        @Test
        public void sprintTest(){
            // 读取spring配置文件
            ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
    
            // 从配置文件中获取对应id所对应的对象
            StudentService studentService = (StudentService) context.getBean("studentService");
            StudentService studentService1 = (StudentService) context.getBean("studentService");
    
            System.out.println(studentService);
            System.out.println(studentService1);
        }

    3:输出结果分析:只执行了一次bean中的构造方法,因为在创建对象时会执行构造方法,说明单利模式只创建了一次构造方法

    执行 StudentService的构造方法
    com.doaoao.impl.StudentServiceImpl@64cd705f
    com.doaoao.impl.StudentServiceImpl@64cd705f 

    ## 在配置文件中将作用域修改为singleton(单例模式)

    <bean id="studentService" class="com.doaoao.impl.StudentServiceImpl" scope="singleton"/>
    
    # 输出结果和上方默认方式相同
    执行 StudentService的构造方法
    com.doaoao.impl.StudentServiceImpl@418e7838
    com.doaoao.impl.StudentServiceImpl@418e7838

    ## 在配置文件中将作用域修改为 prototype(原型模式)每次使用getBean时都会创建

    <bean id="studentService" class="com.doaoao.impl.StudentServiceImpl" scope="prototype"/>
    
    # 输出 <!-- 执行两次构造方法 -->
    执行 StudentService的构造方法
    执行 StudentService的构造方法
    com.doaoao.impl.StudentServiceImpl@5ae50ce6
    com.doaoao.impl.StudentServiceImpl@6f96c77

     ## BeanPostProcessor 接口

    实现该接口的类称为bean后处理器,在该类中重写两个方法"postProcessBeforeInitialization" 和 "postProcessAfterInitialization",在获得某个bean的对象后,在该对象的执行之前和执行之后分别调用上面两个方法,我们可以通过这两个方法实现特定的功能

    以下下为实例:

    package com.doaoao.processor;
    import org.springframework.beans.BeansException;
    import org.springframework.beans.factory.config.BeanPostProcessor;
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    
    public class BeanPostProcessorTest implements BeanPostProcessor {
    
        @Override
        public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
            System.out.println("执行postProcessBeforeInitialization");
            // 注意:这里不能返回null,必须返回bean
            return bean;
        }
    
        @Override
        public Object postProcessAfterInitialization(final Object bean, String beanName) throws BeansException {
            if("studentService".equals(beanName)){
                //创建
                InvocationHandler invocationHandler = ((Object p,Method method,Object[] args)->{
                    // 调用study方法时,使用动态代理对其进行增强
                    if("study".equals(method.getName())) {
                        System.out.println("目标方法开始执行");
                        // 执行目标方法
                        Object result = method.invoke(bean, args);
    
                        System.out.println("目标方法结束执行");
                        return result;
                    }
                    return method.invoke(bean,args);
                });
    
                // 增强bean
                Object proxy = Proxy.newProxyInstance(
                        bean.getClass().getClassLoader(),
                        bean.getClass().getInterfaces(),
                        invocationHandler
                );
                System.out.println("postProcessAfterInitialization执行");
                return proxy;
            }
            return bean;
        }
    }

     ## bean的生命周期

    可以指定bean在初始化和销毁时执行特定的方法

    1:在StudentServiceImpl类中创建两个方法 init 和 destroy

    package com.doaoao.impl;
    import com.doaoao.service.StudentService;
    public class StudentServiceImpl implements StudentService {
        @Override
        public void testDao() {
            System.out.println("Hello World");
        }
        public StudentServiceImpl(){
            System.out.println("执行 StudentService的构造方法");
        }
    
        public void init(){
            System.out.println("执行初始化方法");
        }
        public void destroy(){
            System.out.println("执行销毁方法");
        }
    }

    2:在配置文件中添加两个属性 init-method 和 destroy-method 分别指定初始化方法和销毁方法

        <bean id="studentService" class="com.doaoao.impl.StudentServiceImpl" init-method="init" destroy-method="destroy"/>

     3:修改测试类中的内容

        @Test
        public void sprintTest(){
            // 读取spring配置文件
            ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
    
            // 从配置文件中获取对应id所对应的对象
            StudentService studentService = (StudentService) context.getBean("studentService");
    
            // 调用对象中的指定方法
            studentService.testDao();
    
            // 将context给关闭
            ((ClassPathXmlApplicationContext) context).close();
        }

     4:查看输出(当创建时执行的方法,当销毁时执行的方法)

    执行 StudentService的构造方法
    执行初始化方法
    Hello World
    执行销毁方法

    ...

    本笔记参考自:小猴子老师教程 http://www.monkey1024.com

  • 相关阅读:
    Linux
    Linux
    Linux
    Linux
    Linux
    Python
    Linux
    Python
    MySQL
    Python
  • 原文地址:https://www.cnblogs.com/Doaoao/p/10741333.html
Copyright © 2020-2023  润新知