spring1.1---创建Bean /配置Bean

概要:spring入门,创建bean ,配置bean (主要是在class 这个节点中配置bean 的属性/基于XML 文件)

PART ONE

重点: Bean IOC() AOP(面向切面编程)
轻量级:非 侵入性的。不是jar 包的大小,而是使用spring 开发不用去实现spring 为我们提供的接口,不依赖spring 的API
依赖注入:
面向切面编程
容器: 包含并管理应用对象的生命周期
一站式: 可以整合各种优秀的第三方框架(spring 自身提供类优秀的展现层 springMVC 和持久层 spring JDBC)


Demo1
bean 配置:

  <bean id="helloWorld" class="spring.bean.HelloWorld"       id 是这个bean 的标识,使用反射创建helloworld ;所以HelloWorld 中要有无参构造器
    <property name="name" value="spring"></property>         给属性赋值
   </bean>
   类的设计要符合javabean 的规范

使用:

 
        1. 创建对象
         HelloWorld helloWorld = new HelloWorld();
        2. 设置属性
        helloWorld.setName("spring");*/
        使用spring 之后,这两步都是由spring 帮我们完成
---------------------------------------------------------------------------------------
        1. 创建spring 的 IOC 容器对象
        ApplicationContext ctx = new ClassPathXmlApplicationContext("beanConfig.xml");
        根据指定的xml 文件 创建IOC容器,配置文件中所有的bean 都会被创建实例
        
        2. 从 IOC 容器中获取 Bean 实例
        HelloWorld helloWorld = (HelloWorld) ctx.getBean("helloWorld");
        根据bean 实例的id 获取 bean 的实例
        
        3. 调用方法
        helloWorld.output();
 注:
 ApplicationContext 就代表IOC容器,这是一个接口

PART TWO

IOC

控制反转(Inversion Control):
反转资源的获取方向,之前的资源获取是组件向容器索要资源,现在是容器主动将资源推送给它管理的组件,组件需要做的就是找一个合适的方法接受资源
DI(Denpendency Injection):
(其实是IOC的另一种表达方式) 依赖注入:就是依赖容器将资源注入到需要这个资源的组件中
例如:在Demo1 中 配置Bean 就是将spring 赋给name 其实就是将资源注入;

class A{
private B b ;
public void setB(B b){
B = b;
}
}
容器中有 A B 两个Bean(实例) ,传统的方式是:将B 取出来,通过set 方法赋值b 属性
在spring 解决的办法是:建立 B 实例 和b 之间的关系,将b 指向B 通过set 方法建立。我们在使用的时候只需要获取A 的实例就可以而不用同时获取A B 的实例

容器对组件按需分配

在编程中没有耦合是什么也做不了的。类之间要协作才能实现功能;过高的耦合度代码质量很差
一个类中使用其他类的情况是十分常见的(例如AB),最糟糕的耦合情况A 中直接定义b = new B(); 松耦合 :public void setB(B b);问题在于:
获取A 的实例:A a= (A) ctx.getBean(“a”);
问题在于: 在使用A 的过程中怎么将 B 赋值给A(不使用set 方法)
为什么这里会有不能使用set 方法:
暂时的理解:
比如在写 Controller 的时候要用到service 怎么办 ,不能使用new 这样耦合太高,只能是 Controller 中有一个引用 ;spring要做的事:将这个引用指向 service 这个bean ;实现依赖注入/类的装配

在IOC 中涉及到两点:bean 的创建 依赖如何注入(类之间如何进行装配)


PART THREE

Bean 的配置


一:XML 文件配置Bean

【产生Bean】

< bean id ="bean 的名字" class ="类的全类名"  >
< property name="属性" value="属性的值">< /property>
< /bean>

通过class : 全类名;通过反射在IOC容器中创建Bean 所以要求 对应的类中要有必须要有无参的构造器
通过 id 来标识 容器中Bean id 是唯一的

在spring IOC 创建Bean 之前我们要先实例化 IOC 容器
BeanFactory 是spring框架大的基础设施,是面向spring本身的,ApplicationContext 是面向使用spring框架开发者的,也就是说开发者使用ApplicationContext 创建IOC 容器实例,底层代码的实现是通过 BeanFactory

ApplicationContext 是一个接口,完成IOC容器实例的创建
主要实现类:

1. ClassPathXmlApplicationContext : 从类路径下加载配置文件
2. FileSystemAmlApplicationContext : 从文件系统中加载配置文件 
ApplicationContext 在初始化上下文的时候就是话所有的单例Bean

在这里插入图片描述
【配置Bean 的属性/不包括依赖的对象】
使用value 属性 或者value 子标签

  1. 使用setter 方法注入Bean 的属性值,类中要有set 方法并且符合javabean 规范 ,配置中的name 的值要与之对应
    <property name="name" value="spring"></property>
  2. 使用构造方法
首先类中要有构造函数,可以使用构造函数初始化所有的数据也可以初始化一部分,其他的使用默认初始化
使用构造注入:可以使用 参数的位置和参数的类型 来确定配置中的值赋给谁
    <bean id="student1" class="spring.bean.Student">
        <constructor-arg value="12345" index="0"></constructor-arg>
        <constructor-arg value="你好" index="1"></constructor-arg>
        <constructor-arg value="165" type="double"></constructor-arg>
    </bean>

属性值注入的细节:

1. constructor-arg  可以直接使用它的value 属性  spring 会根据参数的类型将其转换。
 也可以使用 constructor-arg 的子标签 <value></value> 将值的字面值 直接写在 标签中
        <constructor-arg  type="double">
            <value>165</value>
        </constructor-arg>
2. 如果值当中有特殊字符 要使用<![CDATA[值]]>
        <value><![CDATA[nihao~~~~///]]></value>

【引用其他的Bean/引用的注入】
使用value 属性 或者value 子标签
3. 使用setter 方法
< property name =" " ref="引用的Bean 的id" ></property> 建立Bean 之间的引用关系,指向
4. 使用内部 bean 将bean 写在
<property ><bean></bean></property> 或者是 <constructor-arg><bean></bean></constructor-arg>;
5. 使用 构造器
6. 赋空值 : 虽然没有什么意义,但是要知道这种写法 <null/ >
7. 级联属性赋值

Student 类中有属性 Car
在STudent的Bean 配置中配置car 的name 属性值,先要car 依赖注入(要有car 这个bean 才能进行 car 的属性赋值)
 <property name="car.name" value ="baoma"></property>
  1. 集合属性赋值
    < property>< /property > 的子标签 < list> /< set>/< map > 对集合属性赋值;然后在lis标签下进行value <value>值</value> 或者ref <ref bean ="bean 的id "></bean>的配置
<property name=“”>
	<list>
			普通的的值 :<value></value>
			引用  :<ref  bean  = "" />  或者配置内部bean  <ref><bean></bean></ref>
	</list>
</property>

map 集合属性
<property>
	<map>
			<entry key ="  "   value-ref="其他Bean  " ></entry>或者 value = "一般的值"
	</map>
</property>

配置 properties 的属性值(hashMap 的一个子类)
<properties>
	<props>
			<prop key = " ">value</prop>
			<prop key = " ">value</prop>
	</props>
</properties>

注意:
如果你的类中有带参的构造那么一定要进行带参构造的配置

配置单例的集合Bean 让其他的Bean 能够使用它

<util :list id ="标志这个List 其他bean 使用时直接引用id ">
	<ref bean =" "  />
	<value>值</value>
<util:list>

其他的bean 也可以使用这个list 的bean,将他从某个bean 的属性中剥离出来

spring2.5 中给出P属性 配置Bean 的属性
是 < bean > 的一个属性
<bean id=" " name = " 类的全类名" p:age = “值” p:cars-ref = “依赖的引用” p: 类的属性 = “值”>比传统的配置方式更加便捷

二:Bean 自动装配

在< bean>< /bean> 的autowire 的属性里指定自动装配的模式;自动配置主要针对引用属性

  1. ByType : 通过类型进行匹配
  2. ByName : 目标Bean 的id 和当前需要配置的bean 的属性名相同。
    <bean id="car" class="spring.bean.Car" p:name="baima"></bean>
    <bean id="student" class="spring.bean.Student" p:name="lisi" p:id="1" p:age="12" autowire="byName"></bean>
    
  ByName  方式进行配置:已存在 bean 的id为car 这和当前这个bean 中的setter 风格属性名一致,所以可以进行自动配置。不存在这样的bean 就不进行装配
  ByType   方式进行装配:已存在的bean 的类型和当前需要装配的bean 的这个属性的类型一致,但是如果配置文件中存在多个这样的bean 那配置就会报错

神之总结: 在实际的使用中很好使用自动转配。因为你一旦使用自动装配,所有未手动装配的属性都会是自动转配,失去了灵活性

三: Bean 配置之间的关系

这里的关系指的不是对象之间的关系,而是配置之间的关系

继承

  1. spring 允许继承bean 配置,被继承的bean 成为父bean ,继承这个父bean 的bean 称为 子bean ,子bean 继承父bean 中的所 属性配置,也可以覆盖父bean 中的属性配置
    <!--测试bean配置继承-->
    <bean id="car1" class="spring.bean.Car" p:name="baoma"></bean>
    <!--继承 car1 -->
    <bean id="car2" parent="car1"></bean>   使用属性 parent 表明 父bean 
car2 的输出:Car{name='baoma'}
也可以覆盖 父bean ; 将子bean 的配置改为
    <bean id="car2" p:name="biyadi" parent="car1"></bean>
car2 的输出为:Car{name='biyadi'}

  1. 父bean 可以作为模板 设置 bean 的abstract="true" 模板可以不设置 class 属性 ,而让子bean 自己指定自己的类,并且模板bean 没有办法创建bean 实例

依赖
一个bean 中有一个引用属性,在创建这个bean 的时候要求,一定要有当前bean 的依赖,才能创建当前的bean

例如:student 类中有一个属性 car
在自动配置的时候:不存在car 对应的bean 不配置就行(自动配置为null)
在设置依赖之后如果配置文件中没有依赖的bean 就无法创建当前bean 
<bean id="student2" class="spring.bean.Student" p:id="15" p:name="wangwu" p:age="18" depends-on="car" p:car-ref="car"></bean>
设置依赖给了你的bean 一个创建的必然满足的条件

Spring 允许用户通过depends-on 属性设置bean 的牵制依赖,牵制依赖的bean 会在本 bean 实例化之前创建好,如果有多个依赖则用逗号隔开

四:Bean 的生命周期

默认在IOC中配置bean 这个bean 是单例的:IOC只为这个bean 配置创建一个bean 对象。也就是说每一次getBean() 获取到的Bean 对象都是一样的。

例:默认 scope = "singletype"  单例
Car car1 = ctx.getBean("car")
Car car2 = ctx.getBean("car")
System.out.print(car1==car2)  输出结果:true   每次获取的bean 对象是同一个

可以通过bean 的 scope 属性进行配置
scope 默认为: scope = "singleton"    非单例
scope = "prototype"      每一次getBean()  IOC会重新创建一个bean 对象
  1. Bean对象的创建:
    单例模式:singletype
    ApplicationContext ctx=new ClassPathXmlApplicationContext("beanConfig.xml")在创建IOC 容器对象的时候,IOC容器就创建了配置文件中的所有bean 对象
    非单例模式:prototype
    在调用 getBean() 的创建相应的bean 对象,每次调用getBean() 都会创建一个相应bean 的对象

五:外部配置文件配置Bean

对于配置文件,学习到这其实自己也算做一个小小的总结: 首先是xml 文件的配置,然后是外部文件 properties 文件的配置。
外部文件的使用情景:
之前在Javaee JDBC 配置数据库的基本信息的时候 就使用过properties 文件配置数据库的基本信息,在程序中引入properties 文件,获取properties 文件中的值
配置一些基本信息的时候可以直接使用外部文件配置(.peroperties)

例如 : person 中的属性 id  name  age  gender  grade 【使用外部文件进行配置】
bean.properties 
id=12345
name=xiaoming
age=12
gender=man
grade=125

在bean.xml配置文件中的引用外部文件中的属性
spring 提供了一个PropertyPlaceholderConfigurer 的BeanFactory后置处理器,这个处理器允许用户在配置文件中使用${var} 的形式获取外部文件中的bean 属性

在配置文件中添加如下配置:<context:propertity-placeholder location=“classpath:properties 文件名”>
然后就可以在配置文件中使用${name} 获取到外部文件中的name 的值。

<!--引入外部文件配置bean -->
    <context:property-placeholder location="classpath:bean.properties"/>
    <bean id="person" class="spring.bean_properties.Person">
        <property name="id" value="${id}"></property>
        <property name="name" value="${name}"></property>
        <property name="age" value="${age}"></property>
        <property name="gender" value="${gender}"></property>
        <property name="grade" value="${grade}"></property>
    </bean>

可以联想到springboot ,虽然没有那么多的配置文件(没有bean 配置文件) 但是有Application.properties 文件。就是问了完成bean 的外部文件配置。
程序中是类,配置文件中是 bean 的配置。外部也有文件进行配置(保存bean 属性的值,便于配置)。这也解释了为什么在springboot 中配置bruid 数据连接池要在程序中配置声明一个bean :因为在springboot 默认的配置文件中没有bruid 对应的bean 配置。外部文件中配置bruid IOC容器中却没有bean 相对应

SpEL

Spring 的表达式语言(SqEL) :是一个支持运行时查询和操作对象的强大语言表达式;#{SqEL} SqEL 表达式为bean 的属性动态赋值提供了便利

  1. 赋字面值 :
<property name ="id"  value = #{5}> 
<property name ="name" value = #{"小花"}>
 如果是字符串要使用“”/‘’ (单引号/双引号) 赋字面值其实可以不用使用#{}
  1. 赋值对象引用
<property value = "car"  value = #{car2}>  将当前bean 的car 引用指向 :car2 这个bean 
相当于:<property value ="car" ref="car2">
  1. 获取另一个bean 的某个属性值,这是基本的bean 中的配置表达做不到的
<property  value ="name "  value = #{car2.name}>  将car2 这个bean 的name 属性赋值给当前的这个 bean 的name 属性

PART FOUR


六:IOC 容器中Bean 的生命周期方法

springIOC容器可以管理 Bean 的生命周期,管理过程

  1. 通过构造器或工厂方法创建bean 实例
  2. 为bean 的属性赋值和对其他Bean的用(完善Bean 实例)
  3. 调用bean 的初始化方法
  4. 此时的bean 就是可以使用的
  5. 当容器关闭时,调用Bean 的销毁方法
    可以在bean 的指定bean 的初始化和销毁方法;init-method / destroy-menthod

容器对内部的东西进行管理的模式和Servlet容器 对Servlet的管理很相似

代码演示:创建,初始化,销毁

1. Bean:
public class Tree {
    private String name;
    private String type;
    private Integer age;
    Tree(){
        System.out.println("调用构造器");
    }
   //省略大量的set/get和toString() 方法

    销毁函数和初始化函数函数名,内容是自己随意定义的

    1. 初始化函数
    public void init(){
        System.out.println("完成bean 的初始化");
    }
    2.销毁函数
    public void destroy(){
        System.out.println("完成bean 的销毁");
    }
}
2. xml 配置文件:指定bean 的初始化/销毁函数
 <bean id="tree1" class="spring.bean_cycle.Tree" init-method="init" destroy-method="destroy">
        <property name="name" value="沙生树木"></property>
        <property name="age" value="50"></property>
        <property name="type" value="白杨"></property>
    </bean>
3. 测试代码:
 public static void main(String[] args){
        测试初始化和销毁函数
        创建容器
       ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("beans-cycle.xml");

        Tree tree = (Tree)ctx.getBean("tree1");
        System.out.println(tree);

        关闭IOC容器
        ctx.close();
    }
4. 运行结果:
   调用构造器
   完成bean 的初始化
   Tree{name='沙生树木', type='白杨', age=50}
   完成bean 的销毁 

Bean的后置处理器
Bean的后置处理器(针对不同的处理还有不同的处理器)允许在调用初始化方法的前后对Bean 进行额外的处理,Bean 的后置处理器对IOC 容器里的所有Bean 都会逐一的进行处理;例如:bean属性后置处理器:检查bean 属性的正确性或根据特定的标准修改Bean 的属性
Bean 的后置处理器需要实现 interface BeanPostProcessor 在初始化方法执行前和后,Spring 会把每个Bean 实例 分别传递到上述接口的两个方法
postProcessAfterInitalization(Object bean,String beanName)
postProcessBeforeInitalization(Object bean,String beanName)
测试代码:

1. 自定义后置处理器
public class MyPostProcessor implements BeanPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(Object o, String s) throws BeansException {
        System.out.println(s+"初始化之前处理");
        return o;
    }
   会将bean 和bean 的id 传入这个方法
    @Override
    public Object postProcessAfterInitialization(Object o, String s) throws BeansException {
        System.out.println(s+"初始化之后处理");
        return o;
    }
}
2. 配置文件
    <!--配置bean 后置处理器,不需要设置id 扫描时会发现这是一个特殊的bean 会为她自定设置id-->
    <bean class="spring.bean_cycle.MyPostProcessor"></bean>
3. 测试结果:
	tree1初始化之前处理
	完成bean 的初始化
	tree1初始化之后处理
后置处理器的方法十分的强大,你可以在这个方法中对bean 做任意的处理和改变

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值