博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[Js-Spring]Bean的装配
阅读量:4673 次
发布时间:2019-06-09

本文共 8877 字,大约阅读时间需要 29 分钟。

Bean 的装配

Bean 的装配:即 Bean 对象的创建。容器根据代码要求创建 Bean 对象后再传递给代码的过程中,称为 Bean 的装配

Spring 的默认装配方式是容器首先调用 Bean 类的无参构造器,创建空值的实例对象

动态工厂 Bean

有时候项目可能需要通过工厂类来创建 Bean 实例,这时候我们有两种方案

一种是,只配置(创建)一个 Factory 工厂 Bean,在代码中调用 factory 的 getXxx() 方法获取所需要的对象实例,显然这种做法使得耦合度太高(代码里面都写死了调用什么方法)

另一种是(推荐),使用 Spring 的动态工厂 Bean ,factory-bean 指定的是相应的工厂 Bean,factory-method 指定创建所用方法,这时我们至少要定义两个 Bean ,工厂类 Bean,与所要创建的目标类 Bean

 

代码中直接获取 someService 的 Bean 即可

ISomeService service = (ISomeService) ac.getBean("someService");

 

静态工厂 Bean

因为静态工厂是通过调用工厂类的静态方法来创建实例的,所以不需要工厂对象,所以直接在配置文件中配置目标类 Bean 即可,当然工厂类 class 和工厂方法 factory-method 要配置

 

容器中 Bean 的作用域

  • singleton:单态模式。在整个容器中,使用 singleton 定义的 Bean 将会是单例的,只有一个实例
  • prototype:原型模式。每次调用 getBean() 方法都是一个新的实例
  • request:每次 HTTP 请求,都会产生一个不同的 Bean 实例
  • session:对于每个不同的 HTTP session,都将产生一个不同的 Bean 的实例

注:

scope 为 singleton 的 Bean 对象,在容器被创建时即装配好了,这是 Bean 的默认 scope 值

scope 为 protoscope 的 Bean 对象,Bean 实例在使用该 Bean 实例的时候才会被创建

Bean 后处理器

Bean 后处理器是一种特殊的 Bean,容器中所有的 Bean 在初始化的时候,均会执行此类的两个方法。代码中需要自定义后处理器,实现 BeanPostProcessor 接口,该接口中包含两个方法,分别在目标 Bean 初始化完毕之前与之后执行,它们的返回值是:功能被扩展或增强后的Bean对象

在配置文件中配置 Bean 

 

自定义 BeanPostProcessor

package com.neu.ba05;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.lang.reflect.Proxy;import org.springframework.beans.BeansException;import org.springframework.beans.factory.config.BeanPostProcessor;public class MyBeanPostProcessor implements BeanPostProcessor {    public MyBeanPostProcessor() {        super();        System.out.println("初始化MyBeanPostProcessor对象");    }    // bean:当前调用执行Bean后处理器的Bean对象    // beanName:当前调用执行Bean后处理器的Bean对象的ID    @Override    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {        System.out.println("执行MyBeanPostProcessor的postProcessBeforeInitialization()方法");        return bean;    }    @Override    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {        System.out.println("执行MyBeanPostProcessor的postProcessAfterInitialization()方法");        Object proxy = null;        if ("someService1".equals(beanName)) {            proxy = Proxy.newProxyInstance(bean.getClass().getClassLoader(), bean.getClass().getInterfaces(),                    new InvocationHandler() {                        @Override                        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {                            Object result = method.invoke(bean, args);                            if (result != null) {                                result = ((String) result).toUpperCase();                            }                            return result;                        }                    });            return proxy;        }        return bean;    }}

 

观察上面代码,不说也很容易推测出 beanName 是我们获取到的 Bean 实例的名字,bean 是我们获取到的 Bean 实例,返回的是通过 JDK 动态代理得到的强化过的 Bean 实例

定制 Bean 的生命始末

可以为 Bean 定制初始化后的生命行为,也可以为 Bean 定制销毁前的生命行为。

定制的流程为首先这些方法在 Bean 类中事先定义好(方法名随意的 public void 方法),然后在 Bean 标签中添加如下属性,

init-method:指定初始化方法的方法名

destroy-method:指定销毁方法的方法名

注:

若想看到结果,需要

1)Bean 为 singleton 

2)要确保容器关闭,接口 ApplicationContext 没有 close() 方法,但其实现类有。所以,可以将 ApplicationContext 强转为实现类对象关闭

 

package com.neu.ba06;import org.junit.Test;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;public class MyTest {    @Test    public void test01() {        // 加载Spring配置文件,创建Spring容器对象        String resource = "com/neu/ba06/applicationContext.xml";        ApplicationContext ac = new ClassPathXmlApplicationContext(resource);        // 从容器中获取指定的Bean对象        ISomeService service = (ISomeService) ac.getBean("someService");        service.doFirst();        service.doSecond();        // 销毁方法执行有两个要求:        // 1)被销毁的对象需要是singleton的,即单例的        // 2)容器需要显式关闭        ((ClassPathXmlApplicationContext) ac).close();    }}

 

Bean 的生命周期

Bean 实例从创建到最后阶段经过很多过程,执行很多生命周期方法

Step1:调用无参构造函数,创建实例对象

Step2:调用参数的 setter,为属性注入值

Step3:若 Bean 实现了 BeanNameAware 接口,则会执行接口方法 setBeanName(String beanId),使 Bean 类可以获得其在容器中的 id 名称

Step4:若 Bean 实现了 BeanFactoryAware 接口,则会执行接口方法 setBeanFactory(BeanFactory factory),使 Bean 类可以获取到 BeanFactory 对象

Step5:若定义并注册了 Bean 后处理器 BeanPostProcessor,则执行接口方法 postProcessBeforeInitialization()

Step6:若 Bean 实现了 InitializingBean 接口,则执行接口方法 afterPropertiesSet(),该方法在 Bean 的所有属性的 set 方法执行完毕之后执行,标志着 Bean 初始化结束

Step7:若设置了init-method 方法,则执行

Step8:若定义并注册了 Bean 后处理器 BeanPostProcessor,则执行接口方法 postProcessAfterInitialization()

Step9:执行业务方法

Step10:若 Bean 实现了 DisposableBean 接口,则执行接口方法 destroy()

Step11:若设置了 destroy-method 方法,则执行

ISomeService.java

package com.neu.ba07;public interface ISomeService {    public String doFirst();    public void doSecond();}

SomeServiceImpl.java

package com.neu.ba07;import org.springframework.beans.BeansException;import org.springframework.beans.factory.BeanFactory;import org.springframework.beans.factory.BeanFactoryAware;import org.springframework.beans.factory.BeanNameAware;import org.springframework.beans.factory.DisposableBean;import org.springframework.beans.factory.InitializingBean;public class SomeServiceImpl        implements ISomeService, BeanNameAware, BeanFactoryAware, InitializingBean, DisposableBean {    private String adao;    private String bdao;    public void setAdao(String adao) {        System.out.println("Step2:执行setAdao()方法");        this.adao = adao;    }    public void setBdao(String bdao) {        System.out.println("Step2:执行setBdao()方法");        this.bdao = bdao;    }    public SomeServiceImpl() {        System.out.println("Step1:对象的创建");    }    @Override    public String doFirst() {        System.out.println("Step9:(执行主业务方法)执行doFirst()方法");        return null;    }    @Override    public void doSecond() {        System.out.println("执行doSecond()方法");    }    public void initAfter() {        System.out.println("Step7:--初始化之后--");    }    public void preDestory() {        System.out.println("Ste11:---销毁之前---");    }    @Override    public void setBeanName(String name) {        System.out.println("Step3:beanName = " + name);    }    @Override    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {        System.out.println("Step4:获取到BeanFactory容器");    }    @Override    public void afterPropertiesSet() throws Exception {        System.out.println("Step6:当前Bean的初始化工作已经完毕");    }    @Override    public void destroy() throws Exception {        System.out.println("Step10:准备开始销毁工作,进行销毁流程");    }    @Override    public String toString() {        return "SomeServiceImpl [adao=" + adao + ", bdao=" + bdao + "]";    }}

 

MyBeanPostProcessor.java

package com.neu.ba07;import org.springframework.beans.BeansException;import org.springframework.beans.factory.config.BeanPostProcessor;public class MyBeanPostProcessor implements BeanPostProcessor {    // bean:当前调用执行Bean后处理器的Bean对象    // beanName:当前调用执行Bean后处理器的Bean对象的ID    @Override    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {        System.out.println("Step5:执行MyBeanPostProcessor的postProcessBeforeInitialization()方法");        return bean;    }    @Override    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {        System.out.println("Step8:执行MyBeanPostProcessor的postProcessAfterInitialization()方法");                return bean;    }}

 

applicationContext.xml

 

MyTest.java

package com.neu.ba07;import org.junit.Test;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;public class MyTest {    @Test    public void test01() {        // 加载Spring配置文件,创建Spring容器对象        String resource = "com/neu/ba07/applicationContext.xml";        ApplicationContext ac = new ClassPathXmlApplicationContext(resource);        // 从容器中获取指定的Bean对象        ISomeService service = (ISomeService) ac.getBean("someService");        service.doFirst();        ((ClassPathXmlApplicationContext) ac).close();    }}

 

执行结果:(控制台输出)

log4j:WARN No appenders could be found for logger (org.springframework.core.env.StandardEnvironment).log4j:WARN Please initialize the log4j system properly.Step1:对象的创建Step2:执行setAdao()方法Step2:执行setBdao()方法Step3:beanName = someServiceStep4:获取到BeanFactory容器Step5:执行MyBeanPostProcessor的postProcessBeforeInitialization()方法Step6:当前Bean的初始化工作已经完毕Step7:--初始化之后--Step8:执行MyBeanPostProcessor的postProcessAfterInitialization()方法Step9:(执行主业务方法)执行doFirst()方法Step10:准备开始销毁工作,进行销毁流程Ste11:---销毁之前---

 

<bean/>标签的 id 属性与 name 属性

一般情况下,命名<bean/>使用 id 属性,而不使用 name 属性。在没有 id 属性的情况下,name 属性与 id 属性的作用是相同的。但是当<bean/>中含有一些特殊字符的时候,就必须要使用 name 属性了。

id 的命名必须要满足 XML 对 ID 的命名规范:必须以字幕开头,可以包含字母,数字,下划线,连字符,句号,冒号

name 属性值则可以包含各种字符

转载于:https://www.cnblogs.com/jiasq/p/8598364.html

你可能感兴趣的文章
设计模式教程(Design Patterns Tutorial)笔记之一 创建型模式(Creational Patterns)...
查看>>
三 .数据库(表操作)
查看>>
Django 框架篇(七) : 中间件 以及 5种方法
查看>>
python 处理CSV数据
查看>>
tensorflow实战系列(三)一个完整的例子
查看>>
Mybatis:resultMap的使用总结
查看>>
使用U盘安装Ubuntu
查看>>
XFTP 乱码
查看>>
java Int数据工具类
查看>>
下载文件根据浏览器判断文件名,解决兼容性问题
查看>>
当网站不允许上传ASP,CGI,CER等脚本文件时
查看>>
Access 中数据库操作时提示from子句语法错误
查看>>
【备战NOIP】[算法总结] 二分查找
查看>>
sort函数用于vector向量的排序
查看>>
《算法》-- 总结
查看>>
El表达式
查看>>
leetcode-题8-3sum
查看>>
SQL-Server使用点滴(二-系统表)
查看>>
Djiango django跨域 cookie session
查看>>
vue通过webpack打包后怎么运行
查看>>