【一步一步学习spring】spring bean管理(上)

1. spring 工厂类

我们前边的demo中用到的spring 工厂类是ClassPathXmlApplicationContext,从上图可以看到他还有一个兄弟类FileSystemApplicationContext,这个类是加载非classpath路径下的配置文件,本质是一样的。

从继承关系图中可以看到我们经常看到的ApplicationContext,这个是新版本才引入的工厂类接口。在旧版本中是BeanFactory,是在旧版本的基础上增加了几个新功能,如国际化,resourceLoader等。还有一个区别就是加载bean的时机的区别,Beanfactory是在使用bean的时候创建的;ApplicationContext是在加载配置文件的时候就将所有非懒加载的单例创建出来了。

@Test
/**
* 使用beanFactory加载bean
*/
public void demo3() {
    // 老方式的工厂类,需要自己创建Resource对象进行加载。
    BeanFactory beanFactory = new XmlBeanFactory(new ClassPathResource("application-context.xml"));
    // 通过工厂获取类对象
    UserService userService = (UserService) beanFactory.getBean("userService");
    userService.sayHello();
}

2. spring bean管理

2.1 三种实例化Bean的方式

  • 使用类构造器实例化(默认无参数)
  • 使用静态工厂方法实例化(简单工厂模式)
  • 使用实例工厂模式实例化(工厂方法模式)

一般情况都是用第一种方式,只有类的构造非常复杂的情况下才会用后边的俩种。

2.1.1 使用类构造器实例化

  • bean
package com.ioc.demo2;

/**
 * Bean实例化的三种方式:采用无参的构造方法的方式
 */
public class Bean1 {
    public Bean1() {
        System.out.println("Bean1 被实例化了。");
    }
}
  • xml
<!-- 无参数构造方法构建 -->
<bean id="bean1" class="com.ioc.demo2.Bean1"></bean>
  • 调用
@Test
public void demo1() {
    ApplicationContext applicationContext = new ClassPathXmlApplicationContext("application-context.xml");
    Bean1 bean = (Bean1) applicationContext.getBean("bean1");
}

2.1.2 静态工厂方法实例化

  • bean
/**
 * Bean的实例化三种方式:静态工厂实例化方式
 */
public class Bean2 {
}
  • beanFactory
/**
 * Bean2的静态工厂
 */
public class Bean2Factory {

    public static Bean2 createBean2() {
        System.out.println("Bean2Factory 执行了。");
        return new Bean2();
    }
}
  • xml
<!-- 静态工厂的方式 -->
<bean id="bean2" class="com.ioc.demo2.Bean2Factory" factory-method="createBean2"></bean>
  • 调用
@Test
public void demo2() {
    ApplicationContext applicationContext = new ClassPathXmlApplicationContext("application-context.xml");
    Bean2 bean = (Bean2) applicationContext.getBean("bean2");
}

2.1.3 使用实例工厂模式实例化

  • bean
/**
 * 使用实例工厂模式实例化
 */
public class Bean3 {
}
  • beanFactory
/**
 * Bean3的实例工厂
 */
public class Bean3Factory {
    public Bean3 createBean3() {
        System.out.println("Bean3Factory 被调用了。");
        return new Bean3();
    }
}
  • xml
<!-- 实例工厂的方式 -->
<bean id="bean3Factory" class="com.ioc.demo2.Bean3Factory"></bean>
<bean id="bean3" factory-bean="bean3Factory" factory-method="createBean3"></bean>
  • 调用
@Test
public void demo3() {
    ApplicationContext applicationContext = new ClassPathXmlApplicationContext("application-context.xml");
    Bean3 bean = (Bean3) applicationContext.getBean("bean3");
}

2.2 bean的常用配置

2.2.1 id和name

  • 一般情况下,装配一个Bean时,通过指定一个id属性作为Bean的名称
  • id属性在IOC容器中是唯一的
  • name其实也要是唯一的,同id的区别是可以存在特殊字符。这个应该是有历史原因的,不再赘述。

2.2.2 class

  • 设置一个类的全路径的名称,主要作用是IOC容器生成类的实例

2.2.3 scope

类别 说明
singleton(默认) 在SpringIOC容器中仅存在一个Bean实例,Bean以单实例的方式存在
prototype 每次调用getBean()时都会返回一个新的实例
request 每个HTTP请求都会创建一个新的Bean,该作用域仅适用于WebApplicationContext环境
session 同一个HTTP session共享一个Bean,不同的HTTP session使用不同的Bean。该作用域仅适用于WebApplicationContext环境

2.3 spring容器中Bean的生命周期

spring初始化bean或销毁bean时,有时候需要做一些处理工作,因此spring可以在创建和销毁bean的时候调用bean的声明周期方法。

<bean id="xxx" class="...Yoo" init-method="init" destory-method="destory" />

当bean在被载入到容器中时会调用init;当bean从容器中删除的时候调用destroy(scope=singleton有效)

2.3.1 instantiate bean对象实例化

即调用类的构造方法。

2.3.2 populate properties封装属性

即调用类的属性设置方法。

2.3.3 如果Bean实现BeanNameAware,则执行setBeanName

即为该bean设置name的时候调用,可以想象为容器为map,name就是那个key。

2.3.4 如果Bean实现BeanFactoryAware或者ApplicationContextAware设置工厂,则执行setBeanFactory或者上下文对象setApplicationContext

即为该bean设置容器的时候调用。

2.3.5 如果存在类实现BeanPostProcessor(后处理Bean),执行postProcessBeforeInitialization

即在调用init-method之前调用。

2.3.6 如果bean实现InitializingBean,则实行afterPropertiesSet

属性设置后调用。

2.3.7 调用<bean init-method="init">指定的初始化方法

执行init方法。

2.3.8 如果存在类实现BeanPostProcessor(后处理Bean),执行postProcessAfterInitialization

即在调用init-method之后调用。

2.3.9 执行业务处理

即调用bean中的业务方法。

2.3.10 如果Bean实现DisposableBean,执行destory方法

spring自身中的销毁方法。

2.3.11调用<bean destory-method="teardown">指定的销毁方法

执行teardown方法。

2.3.12 相关代码

  • bean
package com.ioc.demo3;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

public class Bean implements BeanNameAware, ApplicationContextAware, InitializingBean, DisposableBean{
    private String name;
    public Bean() {
        System.out.println("第一步:构造方法");
    }
    public void setName(String name) {
        System.out.println("第二步:设置属性");
        this.name = name;
    }
    public void setBeanName(String name) {
        System.out.println("第三步:设置bean的名称:" + name);
    }
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        System.out.println("第四步:设置bean工厂");
    }
    public void afterPropertiesSet() throws Exception {
        System.out.println("第六步:属性设置后");
    }
    public void init() {
        System.out.println("第七步:初始化方法");
    }
    public void run() {
        System.out.println("第九步:业务代码");
    }
    public void destroy() throws Exception {
        System.out.println("第十步:spring自身的销毁");
    }
    public void teardown() {
        System.out.println("第十一步:销毁方法");
    }
}
  • MyBeanPostProcessor
package com.ioc.demo3;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;

public class MyBeanPostProcessor implements BeanPostProcessor {

    // 可以用beanName对要生效的bean做过滤操作
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("第四步:bean初始化前");
        return bean;
    }

    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("第八步:bean初始化后方法");
        return bean;
    }

}
  • xml
<!-- Bean的声明周期============================================ -->
<bean id="bean" class="com.ioc.demo3.Bean" init-method="init" destroy-method="teardown">
    <property name="name" value="xxx"></property>
</bean>
<!-- 注意这个配置是对所有的bean都生效的 -->
<bean class="com.ioc.demo3.MyBeanPostProcessor"></bean>
  • 调用
package com.ioc.demo3;

import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class SpringDemo3 {

    @Test
    public void demo1() {
        // ApplicationContext接口没有close方法,故直接使用了其实现类
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("application-context.xml");
        Bean bean = (Bean)context.getBean("bean");
        bean.run();
        context.close();
    }
}
  • 执行结果
第一步:构造方法
第二步:设置属性
第三步:设置bean的名称:bean
第四步:设置bean工厂
第四步:bean初始化前
第六步:属性设置后
第七步:初始化方法
第八步:bean初始化后方法
第九步:业务代码
第十步:spring自身的销毁
第十一步:销毁方法

2.3.13 使用声明周期中的BeanPostProcessor增强类中的方法

这个本质上是可以对类中的方法做动态代理,为后边的AOP做铺垫。

下边举个栗子:在delete方法前面加一个鉴权的功能,不更改具体的类方法

  • 接口类
package com.ioc.demo3;

public interface BeanDao {

    public void find();
    public void add();
    public void delete();
    public void update();

}
  • 接口实现类
package com.ioc.demo3;

public class BeanDaoImpl implements BeanDao {

    public void find() {
        System.out.println("查询");
    }

    public void add() {
        System.out.println("添加");
    }

    public void delete() {
        System.out.println("删除");
    }

    public void update() {
        System.out.println("更新");
    }

}
  • BeanPostProcessor
package com.ioc.demo3;

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 Object postProcessBeforeInitialization(final Object bean, String beanName) throws BeansException {
        System.out.println("第四步:bean初始化前");
        return bean;
    }

    public Object postProcessAfterInitialization(final Object bean, String beanName) throws BeansException {
        System.out.println("第八步:bean初始化后方法");
        if (beanName.equals("beanDao")) {
            Object proxy = Proxy.newProxyInstance(bean.getClass().getClassLoader(), bean.getClass().getInterfaces(), new InvocationHandler() {

                public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                    if (method.getName().equals("delete")) {
                        System.out.println("鉴权是否是root用户");
                        return method.invoke(bean, args);
                    }
                    return method.invoke(bean, args);
                }
            });
            return proxy;
        }
        return bean;
    }

}
  • xml
<bean class="com.ioc.demo3.MyBeanPostProcessor"></bean>
<bean id="beanDao" class="com.ioc.demo3.BeanDaoImpl"></bean>
  • 调用
package com.ioc.demo3;

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class SpringDemo3 {

    @Test
    public void demo1() {
        ApplicationContext context = new ClassPathXmlApplicationContext("application-context.xml");
        BeanDao beanDao = (BeanDao)context.getBean("beanDao");
        beanDao.add();
        beanDao.delete();
        beanDao.find();
        beanDao.update();
    }
}

原文地址:https://www.cnblogs.com/xxxuwentao/p/9587969.html

时间: 2024-10-06 06:22:05

【一步一步学习spring】spring bean管理(上)的相关文章

Spring的Bean管理(注解管理)

Spring注解的IOC入门步骤: 步骤一:下载spring的开发包 http://repo.spring.io/webapp/search/artifact/?0&q=spring-framework 解压:(Spring目录结构:) * docs:API和开发规范. * libs:jar包和源码. * schema:约束. 步骤二:创建Web项目,引入spring开发jar包 核心jar包四个:bean/Core/Context/Expression Language 两个开发包 : log

spring的bean管理(注解方式)

1.Spring的Bean管理的中常用的注解 @Component:组件.(作用在类上) public interface UserDao {     public void sayHello(); }   @Component(value="userDao")     public class UserDaoImpl implements UserDao {   @Override public void sayHello() {     System.out.println(&qu

spring的bean管理

1.所有的类都可以交给Spring管理 2.如何把一个类交给bean管理? (1)配置applicationContext.xml (2)在xml中写入bean节点配置要交给bean管理的类 3.程序测试 (1)导入spring core container的jar包,spring核心包含以下包: (2)新建applicationContext.xml文件,这个文件要放在src文件夹下边,要不然找不到文件,配置根节点beans,并指定命名空间: <?xml version="1.0&quo

品Spring:bean定义上梁山

认真阅读,收获满满,向智慧又迈进一步... 技术不枯燥,先来点闲聊 先说点好事高兴一下.前段时间看新闻说,我国正式的空间站建设已在进行当中.下半年,长征五号B运载火箭将在海南文昌航天发射场择机将空间站核心舱发射升空.预计用2到3年将空间站建好. 虽然到时你们不让我上去,不过我也为这件事出不了什么力,算扯平了.哈哈,但是我还是会衷心的祝福你. 长征五号火箭首次采用5米大直径的箭体结构,总加注量达到780吨,起飞时共有10台发动机产生1078吨的推力,具备近地轨道25吨.地球同步转移轨道14吨的运载

Spring的bean管理(注解)

前端时间总是用配置文件  内容太多 下面认识一下注解 注解是什么? 1代码里面的特殊标记,使用注解可以完成功能 2注解写法@XXX 3使用注解可以少些很多配置文件 Spring注解开发准备 注解创建准备 1导入Spring的jar包 2创建类 public class User{ public void add(){ System.out.print("add") } } 3创建Spring配置文件 引入约束 开启注解扫描 到包里面扫描类 ,方法,属性上是否有注解 <contex

Spring的bean管理(XML方式)

Bean实例化的方式 1 在spring里面通过配置文件创建对象 2 bean实例化三种方式实现 第一种 使用类的无参构造创建(重点) 如果类里面没有无参数的构造,出现以下异常 第二种 使用静态工厂创建 (1)创建静态的方法,返回类对象 第三种 使用实例工厂创建 (1)创建不是静态的对象,返回类对象 真正的开发中主要使用第一种方法 原文地址:https://www.cnblogs.com/czsy/p/10383710.html

Spring的bean管理(注解)——2017.08.26

1  注解是什么?代码里面的特殊标记,使用注解可以完成功能 注解写法:@注解名称(属性名称=属性值) 注解的地方:类上面,方法上面和属性上面 //类对象上创建对象 @Component(value="user")@Scope(value="prototype") public class User { public void add() { System.out.println("add..."); } } 创建对象有四个注解1 @Compone

框架学习之Spring(一IOC)----HelloWrod

一.概述 Spring是一个开源框架,它的核心是控制反转(IOC)和面向切面(AOP).简单来说,Spring是一个分层的JavaSE/EEfull-stack(一站式)轻量级开源框架. EE 开发分成三层结构: * WEB 层:Spring MVC. * 业务层:Bean 管理:(IOC) * 持久层:Spring 的 JDBC 模板.ORM 模板用于整合其他的持久层框 架 注:Spring框架既可以单独使用 ,也可以结合其他优秀框架一起使用. 二.环境搭建 开发包: 下载地址:http://

Spring中Bean的配置

原创作品,可以转载,但是请标注出处地址http://www.cnblogs.com/V1haoge/p/5859556.html 1.Bean的配置一般都在XML文件中进行配置 2.Bean相关包为:org.springframework.beans和org.springframework.context 3.spring的Bean管理的实现是依靠大量的反射来实现的. 4.Bean定义配置 4.1 Bean标签 ?id属性:用于指定Bean的名称,在Bean被依赖时使用,在获取Bean时使用等

CSDN上看到的一篇有关Spring JDBC事务管理的文章(内容比较全) (转)

JDBC事务管理 Spring提供编程式的事务管理(Programmatic transaction manage- ment)与声明式的事务管理(Declarative transaction management),为不同的事务实现提供了一致的编程模型,这节以JDBC事务为例,介绍Spring的事务管理. 5.3.1  Spring对事务的支持 事务是一组原子(Atomic)操作的工作单元,以数据库存取的实例来说,就是一组SQL指令,这一组SQL指令必须全部执行成功,若因为某个原因未全部执行