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

posted @ 2019-04-25 18:29  一头牛这么多人放  阅读(1286)  评论(0编辑  收藏  举报