天天看点

老板:不懂spring还来做项目?建议离职一、Spring框架二、装配Bean

一、Spring框架

1.1 Spring框架是什么

  • Spring是一种容器框架,用于配置各个组件(bean)并且维护各个组件bean之间的关系
  • Spring框架可以管理Web层,业务层,DAO层,持久层。
  • Spring提倡面向接口编程,配合DI技术可以实现层与层的解耦(主要是WEB层和业务层)
  • Spring框架图
    老板:不懂spring还来做项目?建议离职一、Spring框架二、装配Bean

1.2 一个简单的spring项目

目录结构

  • 引入spring的开发包(最小配置spring.jar以及日志包common-logging.jar)
  • 创建spring的一个核心文件ApplicationContext.xml,该文件一般放在src目录下,该文件中引入xsd文件,可以自定义文件名。
TestSpring
      |---src
          |---com.netease
          |          |---Service
          |                |---HelloService.java
          |                |---ByeService.java
          |          |---Test
          |                |---TestService.java
          |---ApplicationContext.xml
  External Libraries
      |--- spring.jar
      |--- common-logging.jar
      |--- ...
           

代码详情

package com.netease.Service;
public class HelloService {
    private String name;
    private ByeService byeService;      /** 引用了一个ByeService*/

    public String getName() { return name;}
    public void setName(String name) { this.name = name;}

    public ByeService getByeService() { return byeService;}
    public void setByeService(ByeService byeService) { this.byeService = byeService;}

    public void sayHello() {
        System.out.println("hello "+name);
    }
}
           
package com.netease.Service;
public class ByeService {
    private String name;

    public String getName() { return name;}
    public void setName(String name) {this.name = name;}

    public void sayBye() {
        System.out.println("Bye " + name);
    }
}
           
package com.netease.Test;
import com.netease.Service.HelloService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class TestService {
    public static void main(String[] args) {
        /*通过反射机制,在Spring容器中生成对象*/
        /*如果%%.xml放在某个包下,则就变为<包名+文件名>*/
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("ApplicationContext.xml");
        HelloService helloService = (HelloService) applicationContext.getBean("helloService");
        helloService.sayHello();
        helloService.getByeService().sayBye();
    }
}
           

Spring核心容器文件ApplicationContext.xml

  • 在容器文件中配置Bean(Bean有可能是以下各种类型service/dao/domain/action/数据源)
  • Spring框架加载时,会阅读该容器文件,自动创建一个bean对象,并放入内存
  • 学习框架,最重要的就是学习各种配置
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
				http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
				http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">

    <--注意Spring如何配置Bean以及如何维护Bean之间的依赖-->
    <bean id="helloService" class="com.netease.Service.HelloService">
        <--注入属性值-->
        <property name="name">
            <value>Today</value>
        </property>
        <--维护Bean之间依赖,ref指向下一个Bean-->
        <property name="byeService" ref="byeService"/>
    </bean>

    <bean id="byeService" class="com.netease.Service.ByeService">
        <property name="name">
            <value>Yesterday</value>
        </property>
    </bean>
</beans>
           

1.3 Spring框架运行原理图

  • Spring框架什么时候被加载,Spring中配置的bean怎样被创建,Bean与Bean之间的关系如何维护
    老板:不懂spring还来做项目?建议离职一、Spring框架二、装配Bean

1.4 IOC与DI是什么

  • IOC(Inverse Of Controll ) 控制反转:

    所谓控制反转就是把创建对象(bean),和维护对象(bean)的关系的权利从程序中转移到spring的容器(applicationContext.xml),而程序本身不再维护.

  • DI(Dependency Injection) 依赖注入:

    实际上DI和IOC是同一个概念,Spring设计者认为DI更准确表示Spring核心技术

二、装配Bean

2.1 容纳Bean

ApplicationContext方式

  • ApplicationContext ac = new

    ClassPathXmlApplicationContext(“com/netease/bean.xml”)

  • 这句话执行时,不仅实例化了该容器,其中配置的所有scope为singleton的bean全部通过反射机制被实例化,scope为prototype的bean不会被实例化

其他三种加载方式

  • ClassPathXmlApplicationContext:从类路径中加载。
  • FileSystemXmlApplicationContext:从文件系统加载,需要全路径
  • XmlWebApplicationContext:从web系统中加载。

好处:预先加载,速度快;缺点:耗内存

Bean的作用域,即scope

老板:不懂spring还来做项目?建议离职一、Spring框架二、装配Bean

Bean工厂方式

  • BeanFactory factory = new XmlBeanFactory(new

    ClassPathResource(“com/netease/bean.xml”))

  • 这句话执行时,仅实例化了该容器,容器中的bean不被实例化,只有当你使用factory.getBean("***")获取某个bean时,才实例化该bean对应的对象。类似于延迟实例化
  • 好处:节约内存;缺点:速度慢
  • 一般没有特殊要求,都采用ApplicationContext方式实例化(90%),移动端可采用Bean工厂方式

2.2 Bean生命周期

完整生命周期步骤如下(通常只用到加粗的几步):

  1. 实例化:程序加载ApplicationContext文件,并把bean(scope=singleton)实例化到内存
  2. 设置属性:调用set方法设置bean中指定的属性 如果你实现了BeanNameAware接口, 则可以通过BeanName
  3. 如果你实现了BeanFactoryAware接口,则可以获取BeanFactory
  4. 如果你实现了ApplicationContextAware接口,则可以获取ApplicationContext
  5. 如果bean和一个后置处理器关联,则会自动去调用 postProcessBeforeInitialization()方法
  6. 如果你实现InitializingBean接口,则会调用afterPropertiesSet()方法
  7. 如果设置了,则可以在bean文件中定义自己的初始化方法init.
  8. 如果bean和一个后置处理器关联,则会自动去调

    postProcessAfterInitialization()方法

  9. 使用bean 容器关闭
  10. 可以通过实现DisposableBean接口来调用方法 destory,用来关闭资源等
  11. 可以在 调用定制的销毁方法destroy

ApplicationContext方式

老板:不懂spring还来做项目?建议离职一、Spring框架二、装配Bean

Bean工厂方式

老板:不懂spring还来做项目?建议离职一、Spring框架二、装配Bean

2.3 装配Bean

2.3.1 什么是装配Bean

告诉容器有哪些Bean以及容器如何使用依赖注入将它们配合在一起。

2.3.2 装配方法

  • 在XML进行显式配置
  • 在Java中进行显示配置
  • 隐式的bean发现机制和自动装配

2.3.3 面向XML的装配方法

2.3.3.1 添加一个Bean

  • 基本配置:一个bean ID + 全称类名
<beans>
   <bean id="foo" class="...Foo"/>
   <bean id="bar" class="...Bar"/>
</beans>
           
  • scope属性
<beans>
  <bean id="foo" scope="prototype/singleton" class="...Foo"/>
  <bean id="bar" class="...Bar"/>
</beans>
           

注意尽量使用默认的singleton,以防占用太大内存,影响程序性能

init-method 和destroy-method属性

用途:在Spring实例化或者销毁bean时做一些处理工作

使用方法:

  1. 声明方式:在XML文件中先声明该Bean拥有的初始化和销毁方法的函数名。在bean.java中实现init和destroy方法,函数名可自定义
  1. 标签方式:不需要在xml文件中声明初始化和销毁方法,在bean.java中采用标签方式声明初始化和销毁方法
@PostConstruct
public void ini(){…}
@PreDestroy
public void destroy(){…}
           

其他进行初始化和销毁处理的方法:

Spring还提供了两个接口供bean.java使用,来进行实例化或者销毁时的处理,但不推荐

2.3.3.2 通过set方法注入属性和依赖

通过元素的子元素注入属性和依赖

  • 注入简单属性(基本类型和String)
<bean id="foo" class="...Foo">
      <property name="name">
            <value>tom</value>
      </property>
</bean>
           

注入依赖

  • 引用其他的Bean
<bean id="foo" class="...Foo">
      <property name="name">
            <ref bean="bar">
      </property>
</bean>
<bean id="bar" class="...Bar">
</bean>
           
  • 内部bean
<bean id="foo" class="...Foo">
  <property name="bar">
        <bean class="...Bar">...</bean>
  </property>
</bean>
           
  • 注入集合属性(数组,List,Set,Map)

设置null

<property name="barlist">
       <null/>
</property>
           

数组

<-- 给数组注入值 -->
<property name="empName">
  <list>
    <value>小明</value>
    <value>李雷</value>
    <value>韩梅梅</value>
  </list>
</property>
           

List

<-- 给list注入值 list 中可以有相等的对象 -->
  <property name="empList">
   	<list>
   		<ref bean="emp2" />
   		<ref bean="emp1"/>
   		<ref bean="emp1"/>
   	</list>
  </property>
           

Set

<-- 给set注入值 set不能有相同的对象 -->
  <property name="empsets">
   	<set>
   		<ref bean="emp1" />
   		<ref bean="emp2"/>
   		<ref bean="emp2"/>
   	</set>
  </property>
           

Map

<-- 给map注入值只要key不同即可 -->
  <property name="empMaps">
   	<map>
   		<entry key="11" value-ref="emp1" />
   		<entry key="22" value-ref="emp2"/>
   		<entry key="33" value-ref="emp1"/>
   	</map>
 </property>
           

property

<property name="pp">
	<props>
		<prop key="pp1">abcd</prop>
		<prop key="pp2">hello</prop>
	</props>
</property>
           

Bean的继承

  1. public class Student有name和age两个属性
  2. public class Gradate extends
  3. Student 有degree属性 在ApplicationContext文件中体现配置
即student中配置过的属性graduate可以不配置 如果配置,则会覆盖父类的属性
<-- 配置一个学生对象 -->
  <bean id="student" class="com.hsp.inherit.Student">
  	<property name="name" value="顺平" />
  	<property name="age" value="30"/>
  </bean>
  <-- 配置Grdate对象 -->
  <bean id="grdate" parent="student" class="com.hsp.inherit.Gradate">
  	<-- 如果自己配置属性name,age,则会替换从父对象继承的数据  -->
  	<property name="name" value="小明"/>
  	<property name="degree" value="学士"/>
  </bean>
           

2.3.3.3 通过构造器注入属性

通过元素的子元素注入属性

<bean id="test" class ="...Test">
  <constructor-arg index="0" type="java.lang.String" value="朱洁" />
  <constructor-arg index="1" type="int" value="20"/>
  <constructor-arg  index="2" type="double" value="34.5" />
</bean>
           

2.3.3.4 分散配置

通过在ApplicationContext.xml文件中配置context:property-placeholder 引入属性文件,有多个需要使用’,'号间隔.

步骤如下:

  1. 配置属性文件db.property
name=scott
 drivername=oracle:jdbc:driver:OracleDirver
 url=jdbc:oracle:thin:@127.0.0.1:1521:hsp
 pwd=tiger
           
  1. 在ApplicationContext.xml文件中引入db.properties文件,两种方式

    第一种

第二种

<bean id="dbPropertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
    <property name="locations">
         <list>
         <value>xx/yy/db.properties</value>
         <value>xx/yy/db2.properties</value>
         </list>
      </property>
</bean>
           
  1. 在ApplicationContext.xml文件中配置bean,采用占位符$方式
<bean id="dbutil" class="com.hsp.dispatch.DBUtil">
<property name="name" value="${name}" />
<property name="drivername" value="${drivername}" />
<property name="url" value="${url}" />
<property name="pwd" value="${pwd}" />
</bean>
           

2.3.3.5 自动装配

  • 通过autowire属性装配
<bean id="foo" class="...Foo" autowire="autowire
   type"> 
           

有四种自动装配类型:

  • byName寻找和属性名相同的bean,若找不到,则装不上。(属性名和bean id名必须相同)
  • byType:寻找和属性类型相同的bean,找不到,装不上,找到多个抛异常。
  • constructor:查找和bean的构造参数一致的一个或多个bean,若找不到或找到多个,抛异常。按照参数的类型装配
  • autodetect: (3)和(2)之间选一个方式。不确定性的处理与(3)和(2)一致。
  • defualt : 这个需要在
  • no : 不自动装配,这是autowrite的默认值。
    老板:不懂spring还来做项目?建议离职一、Spring框架二、装配Bean

    default说明

    需要在

  • 如果在指定了default-atuowrite后,所有的bean的默认的autowire就是中指定的装配方法;
  • 如果没有在指定defualt-autorwire,则默认是defualt-autorwire=”no”,所有的bean则默认不自动装配,除非自己配置autowire

篇幅有限,暂时更新到这里啦!下一篇尽快上传~

看到这里的小伙伴,如果你喜欢这篇文章的话,别忘了转发、收藏、留言互动!

最近我新整理了一些Java资料,包含面经分享、模拟试题、和视频干货,如果你需要的话,欢迎私信我!

如果对文章有任何问题,欢迎在留言区和我交流~

还有,关注我!关注我!关注我!

继续阅读