下文:SpringIOC 二—— 容器 和 Bean的深入理解

写在前面

这篇文章去年写的,缘起于去年某段时间被领导临时“抓壮丁”般的叫过去做java开发,然后在网上找了一个 SpringMVC 的 demo,学习一下,然后依葫芦画瓢,开始了自己的项目开发,也还顺利完成了任务。在使用 SpringMVC 的过程中,我被这个被称作“最优秀”的 java 框架 —— Spring 深深地吸引了,那些曾经掌握的多种设计模式的思想在其中都有实现,比如工厂模式、单例模式、观察者模式等等,于是在工作之余认真地学习了这个框架。

学习新东西总是令人兴奋的,然而大多数学过的知识很容易又会忘记,所以便想整理一下,写点笔记,方便自己以后复习查看。

部分参考资料:

《Spring实战(第4版)》

《轻量级 JavaEE 企业应用实战(第四版)》

Spring 官方文档

W3CSchool Spring教程

易百教程 Spring教程

一、Spring简介

Spring是一个开源框架,Spring是于2003年兴起的一个轻量级的Java开发框架,由Rod Johnson在其著作Expert One-On-One J2EE Development and Design中阐述的部分理念和原型衍生而来。它是为了解决企业应用开发的复杂性而创建的。框架的主要优势之一就是其分层架构,分层架构允许使用者选择使用哪一个组件。Spring提供了约20多个组件,开发者可以根据自己需要选择组件。Spring的核心是控制反转(IoC)和面向切面编程(AOP)

  • IoC:控制反转。

    控制反转(Inversion of Control),又叫依赖注入(Dependency Injection)。举例来说,在之前的操作中,比方说有一个类,我们想要调用类里面的方法(不是静态方法),就要创建类的对象,使用对象调用方法实现。对于Spring来说,Spring创建对象的过程,不是在代码里面实现的,而是交给Spring来进行配置实现的。
  • AOP:面向切面编程。

    面向切面编程(Aspect Orient Programming)支持允许将一些通用的任务入安全、事物、日志、缓存等进行集中式处理,从而提供了更好的复用,AOP通常用来处理一些具有横切性质的系统级服务。

二、Hello Spring 实例

从最简单的 Hello,Spring 例子来体会一下使用 Spring 框架。首先看看不使用 Spring 框架的代码:

HelloSpring.java 类:

package com.sharpcj;

public class HelloSpring {
private String name; public void sayHello() {
System.out.println("Hello," + name + "!");
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
}
}

Test.java 类:

package com.sharpcj;

public class Test {
public static void main(String[] args) {
HelloSpring hs = new HelloSpring();
hs.setName("Spring");
hs.sayHello();
}
}

输出结果:

Hello,Spring!

下面我们用 Spring 框架来实现这个例子。

Spring 框架官方下载地址: http://repo.springsource.org/libs-release-local/

Spring 框架阿里云下载地址:http://maven.aliyun.com/nexus/content/groups/public/springframework/

添加从 Spring 框架核心 JAR 文件:

  • commons-logging-1.1.1
  • spring-aop-5.0.6.RELEASE
  • spring-aspects-5.0.6.RELEASE
  • spring-beans-5.0.6.RELEASE
  • spring-context-5.0.6.RELEASE
  • spring-context-support-5.0.6.RELEASE
  • spring-core-5.0.6.RELEASE
  • spring-expression-5.0.6.RELEASE
  • spring-instrument-5.0.6.RELEASE
  • spring-instrument-tomcat-5.0.6.RELEASE
  • spring-jdbc-5.0.6.RELEASE
  • spring-jms-5.0.6.RELEASE
  • spring-messaging-5.0.6.RELEASE
  • spring-orm-5.0.6.RELEASE
  • spring-oxm-5.0.6.RELEASE
  • spring-test-5.0.6.RELEASE
  • spring-tx-5.0.6.RELEASE
  • spring-web-5.0.6.RELEASE
  • spring-webmvc-5.0.6.RELEASE
  • spring-webmvc-portlet-5.0.6.RELEASE
  • spring-websocket-5.0.6.RELEASE

这里只是使用Spring的基本功能,所以需要使用到下面的这几个Jar包:

这里我使用的 idea,用 gradle 编译的(用 maven 过程类似)。为了提高下载速度,我使用了阿里云的 maven 仓库,然后添加依赖,最新稳定版本是 5.0.6 , build.gradle文件部分截图:

代码更改如下:

HelloSpring.java 类

package com.sharpcj;

public class HelloSpring {
private String name; public void sayHello() {
System.out.println("Hello," + name + "!");
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
}
}

Test.java 类

package com.sharpcj;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext; public class Test {
public static void main(String[] args) {
ApplicationContext context = new FileSystemXmlApplicationContext("src/beans.xml");
HelloSpring hs = context.getBean("helloSpring", HelloSpring.class);
hs.sayHello();
}
}

此时在 src 目录下新建了一个文件 beans.xml :

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"> <bean id="helloSpring" class="com.sharpcj.HelloSpring">
<property name="name" value="Spring"/>
</bean> </beans>

此时运行 Test.java 的 main 方法,打印结果如下:

Hello,Spring!

这样我们就用 Spring 框架实现了最简单的 Hello Spring 程序。

三、认识 spring 容器和 Bean

上面用 Spring 框架实现的代码中,我们在 Test.java 类中,并没有通过 “new HelloSpring()” 这样的调用 Spring 构造方法去创建 HelloSpring 的对象,而是使用 Spring 核心容器创建的。

  • 第一步是我们使用框架 API FileSystemXmlApplicationContext() 来创建应用程序的上下文。这个 API 加载 beans 的配置文件并最终基于所提供的 API,它处理创建并初始化所有的对象,即在配置文件中提到的 beans。

  • 第二步是使用已创建的上下文的 getBean() 方法来获得所需的 bean。这个方法使用 bean 的 ID 返回一个最终可以转换为实际对象的通用对象。一旦有了对象,你就可以使用这个对象调用任何类的方法。能通过这种方式创建的对象,一定是在 beans.xml 文件中配置的。

Spring 核心容器就好像是一个超级大的工厂,在配置文件中配置过的对象都会被当成 Spring 容器管理的对象。Spring 把容器中的一切对象统称为 Bean 。 Spring 中的 Bean 与传统的 java Bean 不同,对 Spring 而言,任何一个 java 类,都可以当成是 Bean 来处理。

四、Spring容器装配Bean的三种方式

  • 在XML中进行装配
  • 自动装配 bean
  • 在Java中进行装配

还是用上面 HelloSpring 的例子,该例子实在过于简单,只有一个 bean, 没有涉及到两个 bean 之间的依赖关系,不过还是可以用它来理解Spring容器装配Bean的三种装配方式。为了说明依赖注入的场景,举个其它例子:

人用笔写字。伪代码如下:

Pen 类:

public class Pen {
// property 暂不关心
}

Person 类:

public class Person {
private Pen pen; public Person(Pen pen) {
this.pen = pen;
} public Pen getPen() {
return this.pen;
} public void setPen(Pen pen) {
this.pen = pen;
} // 这里我们暂不关心该方法
public void write() { }
}

下面对于这种依赖关系,将分别用伪代码来说明构造注入和设置注入。

在 XML 中进行装配

基本使用

上面例子即是,不再赘述。

依赖注入

如果存在多个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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"> <bean id="pen" class="com.sharpcj.Pen"> </bean> <bean id="person" class="com.sharpcj.Person">
<constructor-arg name = "pen", ref = "pen">
</bean>
</beans>

设值注入:

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"> <bean id="pen" class="com.sharpcj.Pen"> </bean> <bean id="person" class="com.sharpcj.Person">
<property name = "pen", ref = "pen">
</bean>
</beans>

4.2 自动装配 bean

基本使用

com.sharpcj.HelloSpring.java 代码如下:

package com.sharpcj;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component; @Component
public class HelloSpring {
private String name; public void sayHello() {
System.out.println("Hello," + name + "!");
} public String getName() {
return name;
} @Value("Spring")
public void setName(String name) {
this.name = name;
}
}

创建类 com.sharpcj.HelloConfig.java用来开启组件扫描:

package com.sharpcj;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration; @Configuration
@ComponentScan
public class HelloConfig {
}

修改com.sharpcj.Test.java

package com.sharpcj;

import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext; public class Test {
public static void main(String[] args) {
ApplicationContext context = new AnnotationConfigApplicationContext(com.sharpcj.HelloConfig.class);
HelloSpring hello = context.getBean("helloSpring", HelloSpring.class);
hello.sayHello();
}
}

@Component 注解的类即为 Bean 。 @Configuration 注解的即为配置文件,@ComponentScan 注解表示开启自动扫描,默认扫描该配置类所在的包,如果扫描其它包,多个包,形式如下:

@Configuration
@ComponentScan(basePackageClasses = {com.a.A.class, com.b.B.class})

也可以每个包内配置之后,再配置一个总的配置文件:

@Configuration
@Import({com.a.AConfig.class, com.b.BConfig.class})
public class TotalConfig {
}

依赖注入

如果存在多个Bean, 之间有依赖关系:

// pen 类:

@Component
public class Pen {
// property 暂不关心
}

构造注入:

@Component
public class Person { private Pen pen; @Autowired
public Person(Pen pen) {
this.pen = pen;
} public Pen getPen() {
return this.pen;
} public void setPen(Pen pen) {
this.pen = pen;
} // 这里我们暂不关心该方法
public void write() { }
}

设值注入:

@Component
public class Person { private Pen pen; public Pen getPen() {
return this.pen;
} @Autowired
public void setPen(Pen pen) {
this.pen = pen;
} // 这里我们暂不关心该方法
public void write() { }
}

通过 java 代码进行装配

基本使用

此时 java 类无需使用注解。

同样创建一个类,com.sharpcj.HelloConfig.java来进行装配 Bean。

package com.sharpcj;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; @Configuration
public class HelloConfig {
@Bean
public HelloSpring helloSpring(){
return new HelloSpring();
}
}

被 @Bean 标注的方法返回的即为唯一 Bean(默认单例模式),方法名随便取。

Test:

ApplicationContext context=new AnnotationConfigApplicationContext(com.sharpcj.HelloConfig.class);
Person person = context.getBean(Person.class);
person.write();

依赖注入

如果存在多个Bean, 之间有依赖关系:

构造注入:

@Configuration
public class PConfig {
@Bean
public GPen hehe() {
return new GPen();
} @Bean
public QPen haha() {
return new QPen();
} @Bean
public Person xixi() {
Person person = new Person(hehe());
return person;
}
}

设值注入:

@Configuration
public class PConfig {
@Bean
public GPen hehe() {
return new GPen();
} @Bean
public QPen haha() {
return new QPen();
} @Bean
public Person xixi() {
Person person = new Person();
person.setPen(hehe());
return person;
}
}

写在后面

这篇文章记录了Spring容器和Bean的概念,Spring 的基本使用,以及Spring容器装配Bean的三种方式。关于Spring 容器的知识点比较多,下篇文章接着写点 Spring 容器装配 Bean 的高级知识点。

Spring IOC 一——容器装配Bean的简单使用的更多相关文章

  1. (转)java之Spring(IOC)注解装配Bean详解

    java之Spring(IOC)注解装配Bean详解   在这里我们要详细说明一下利用Annotation-注解来装配Bean. 因为如果你学会了注解,你就再也不愿意去手动配置xml文件了,下面就看看 ...

  2. 05_IOC容器装配Bean(注解方式)

    IOC容器装配Bean(注解方式) 1.使用注解方式进行Bean注册 xml 方式: <bean id="" class=""> spring2.5 ...

  3. 04_IOC容器装配Bean(xml方式)

    IOC容器装配Bean(xml方式) 1.Spring 提供配置Bean三种实例化方式 1)使用类构造器实例化(默认无参数) <bean id="bean1" class=& ...

  4. Spring实战3:装配bean的进阶知识

    主要内容: Environments and profiles Conditional bean declaration 处理自动装配的歧义 bean的作用域 The Spring Expressio ...

  5. Spring实战2:装配bean—依赖注入的本质

    主要内容 Spring的配置方法概览 自动装配bean 基于Java配置文件装配bean 控制bean的创建和销毁 任何一个成功的应用都是由多个为了实现某个业务目标而相互协作的组件构成的,这些组件必须 ...

  6. SpringIOC容器装配Bean

    Spring 的core Container(Spring的核心容器)有四大部分:bean.context.core.expression 在进行Bean的配置时候,需要添加四个jar包 如下: 分别 ...

  7. Spring IOC(八)bean 的创建

    Spring IOC(八)bean 的创建 Spring 系列目录(https://www.cnblogs.com/binarylei/p/10198698.html) 参考: 每天用心记录一点点.内 ...

  8. Spring容器装配Bean的三种方式

    欢迎查看Java开发之上帝之眼系列教程,如果您正在为Java后端庞大的体系所困扰,如果您正在为各种繁出不穷的技术和各种框架所迷茫,那么本系列文章将带您窥探Java庞大的体系.本系列教程希望您能站在上帝 ...

  9. IoC容器装配Bean(xml配置方式)(Bean的生命周期)

    1.Spring管理Bean,实例化Bean对象 三种方式 第一种:使用类构造器实例化(默认无参数) package cn.itcast.spring.initbean; /** * 使用构造方法 实 ...

随机推荐

  1. 【zTree】zTree根据后台数据生成树并动态设置前面的节点复选框的选中状态

    0.页面中准备树的ul <ul id="treeDemo10" class="ztree" style="display: none;" ...

  2. 12.1——类的定义与声明,隐含的this指针

    类的定义与声明: (1)将const放在成员函数的形参列表之后,可以将将成员函数声明为常量,而它的意思是函数不能改变所操作的数据成员 这里必须在声明和定义处都加上const. (2)成员函数有一个隐含 ...

  3. 使用 Apache Lucene 和 Solr 4 实现下一代搜索和分析

    使用 Apache Lucene 和 Solr 4 实现下一代搜索和分析 使用搜索引擎计数构建快速.高效和可扩展的数据驱动应用程序 Apache Lucene™ 和 Solr™ 是强大的开源搜索技术, ...

  4. mySQL windows 服务

    https://www.jizhuba.com/kejiyouxi/20171001/6006.html

  5. Two Paths--cf14D(树的直径)

    题目链接:http://codeforces.com/problemset/problem/14/D D. Two Paths time limit per test 2 seconds memory ...

  6. BCD工具类(8421)

    目录 1.BCD介绍 (1)BCD码(Binary-Coded Decimal)亦称二进码十进数.用4位二进制数来表示1位十进制数中的0~9这10个数码.用二进制编码的十进制代码. (2)BCD码可分 ...

  7. response对象学习

    import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpSer ...

  8. Nginx配置upstream实现负载均衡及keepalived实现nginx高可用

    (原文链接:http://www.studyshare.cn/blog-front//blog/details/1159/0 ) 一.准备工作 1.准备两个项目,发布到不同的服务器上,此处使用2个虚拟 ...

  9. Go -- 多个go文件包名都是main

    用go run *.go 或 go run one.go two.go main.go

  10. javascript创建对象总结(javascript高级程序设计)

    1.工厂模式 这样的模式抽象创建详细对象的过程.用函数封装特定的接口来创建类. function createStudent(name) { var o = new Object(); o.name ...