Spring框架是 Java 平台的一个开源的全栈(Full-stack)应用程序框架和控制反转容器实现,通常被直接称为 Spring。该框架的一些核心功能理论上可用于任何 Java 应用,但 Spring 还为基于Java企业版平台构建的 Web 应用提供了大量的拓展支持。虽然 Spring 没有直接实现任何的编程模型,但它已经在 Java 社区中广为流行,基本上彻底代替了企业级JavaBeans(EJB)模型php
—— 维基百科java
上面的一段引言,基本阐述了这个Spring框架,而一门框架的流行,天然有其必然之处,怎么理解框架这个词呢?web
不扯什么太专业的名词,我们就讲点大白话,你们应该都听过 “框架是一个半成品” ,这句话没毛病,框架就是封装了不少不少的代码,而后你只须要直接调用它提供给你的 API 就能直接使用它的功能,省了我们不少功夫。最近闲在家,给你们整个比较通俗的例子——鸡蛋灌饼的制做spring
使用这个提供好的面饼,就能够省去咱们不少功夫,只须要在面饼上进行加工就能够了,这和使用框架是一个道理,框架就是一个半成品,即节省了咱们开发的成本,又可让咱们在这个框架的基础上进行自定义的加工apache
但愿你们能看完个人文章,别光记住了鸡蛋灌饼怎么作(捂脸),毕竟我感受这是一个技术贴编程
捞一下,贴一个弟弟我全手工作的灌饼(狗头保命)设计模式
我好像说的有点多了,赶忙拉回来,框架的最初意愿固然都是为了简化开发,帮助开发者快速的完成项目需求,说的确切一点,就是框架中结合了不少的设计模式,可让你 “动态” 的开发,将代码实现了通用性,通常本身写的简单的代码,都涉及太多的 “硬编码” 问题了 ,而若是本身去写这些设计模式又太复杂了数组
因此,作不了巨人,不如咱们就学习站在巨人的肩膀上! Let's go!缓存
做为一篇新手都能看懂的文章,开始就一堆 IOC AOP等专业名词扔出去,好像是不太礼貌,我得把须要铺垫的知识给你们尽可能说一说,若是对这块比较明白的大佬,直接略过就OK了安全
耦合,就是模块间关联的程度,每一个模块之间的联系越多,也就是其耦合性越强,那么独立性也就越差了,因此咱们在软件设计中,应该尽可能作到低耦合,高内聚
生活中的例子:家里有一条串灯,上面有不少灯泡,若是灯坏了,你须要将整个灯带都换掉,这就是高耦合的表现,由于灯和灯带之间是紧密相连,不可分割的,可是若是灯泡能够随意拆卸,并不影响整个灯带,那么这就叫作低耦合
代码中的例子:来看一个多态的调用,前提是 B 继承 A,引用了不少次
A a = new B();
a.method();
复制代码
若是你想要把B变成C,就须要修改全部new B()
的地方为 new C()
这也就是高耦合
若是若是使用咱们今天要说的 spring框架 就能够大大的下降耦合
A a = BeanFactory().getBean(B名称);
a.method();
复制代码
这个时候,咱们只须要将B名称改成C,同时将配置文件中的B改成C就能够了
常见的耦合有这些分类:
当一个模块直接修改或操做另外一个模块的数据,或者直接转入另外一个模块时,就发生了内容耦合。此时,被修改的模块彻底依赖于修改它的模块。 这种耦合性是很高的,最好避免
public class A {
public int numA = 1;
}
public class B {
public static A a = new A();
public static void method(){
a.numA += 1;
}
public static void main(String[] args) {
method();
System.out.println(a.numA);
}
}
复制代码
两个以上的模块共同引用一个全局数据项就称为公共耦合。大量的公共耦合结构中,会让你很难肯定是哪一个模块给全局变量赋了一个特定的值
一组模块都访问同一全局简单变量,并且不经过参数表传递该全局变量的信息,则称之为外部耦合 从定义和图中也能够看出,公共耦合和外部耦合的区别就在于前者是全局数据结构,后者是全局简单变量
控制耦合 。一个模块经过接口向另外一个模块传递一个控制信号,接受信号的模块根据信号值而进行适当的动做,这种耦合被称为控制耦合,也就是说,模块之间传递的不是数据,而是一些标志,开关量等等
标记耦合指两个模块之间传递的是数据机构,如高级语言的数组名、记录名、文件名等这些名字即为标记,其实传递的是这个数据结构的地址
模块之间经过参数来传递数据,那么被称为数据耦合。数据耦合是最低的一种耦合形 式,系统中通常都存在这种类型的耦合,由于为了完成一些有意义的功能,每每须要将某些模块的输出数据做为另 一些模块的输入数据
两个模块之间没有直接关系,它们之间的联系彻底是经过主模块的控制和调用来实现的
讲完了Spring框架的一些优势,如今咱们来看一下,Spring框架的结构,来对咱们要学习的框架有一个总体的认识,下面是一张官方的结构图
显而易见,Spring框架是一个分层的架构,根据不一样的功能,分红了多个模块,而这些模块都是能够单独或者组合使用的,下面咱们来简单的介绍一下每个部分
首先将目光放到 CoreContainer 上,它是 Spring 框架最基本也是最核心的部分,其余部分的模块,都是基于这一部分创建的
提供 Spring框架的基本功能,分为图中四个模块,核心容器中重要的组件就是 BeanFactory ,本质就是实现了工厂模式,且它使用了 IoC(控制反转)模式,将程序的配置以及依赖性规范与实际程序的代码分开
JDBC:提供了一个JDBC抽象层,减小了一些重复无聊的JDBC代码,提高了开发效率
ORM:提供了对流行对象关系映射API的集成层 (JPA、JDO、Hibernate、 mybatis )
OXM:提供了一个支持对象/XML映射实现的抽象层( JAXB、Castor、XMLBeans、JiBX 、XStrea )
JMS:Java消息服务, 包含用于生产和消费消息的功能
Transactions:事务模块,用于支持实现特殊接口和全部的POJO的类的编程和声明式事物管理
Web:提供了基本的 Web 的集成功能,例如多部分文件上传功能,以及初始化了一个使用了Servlet监听器和面向Web应用程序上下文的 IoC 容器,它还包含一个HTTP客户端和Spring远程支持的相关部分
Servelt:包含 Spring 模型—视图—控制器 (MVC) ,用来实现Web应用
WebSocket:Spring4.0之后新增的模块,它提供了WebSocket和SocketJS的实现
Portlet:就好像是Servlet通常,它提供了Portlet环境下的MVC实现
AOP:提供了面向切面编程的能力,容许定义方法拦截器和切入点,按功能分离代码,下降耦合性,能够实现一些面向对象编程中不太好实现的功能
Aspects:提供与 AspectJ 的继承,是一个功能强大且成熟的面向切面编程的框架
Instrumentation:提供了类工具的支持和类加载器的实现,能够在特定的应用服务器中使用
Messaging: 它提供了对消息传递体系结构和协议的支持
Test:其支持使用 JUnit 或者 TestNG,能够实现单元测试,集合测试等测试流程
首先,咱们简单的模拟一个对帐户进行添加的操做,咱们先采用咱们之前经常使用的方式进行模拟,而后再给出改进方案,再引出今天要将的 Spring 框架,能帮助更好的理解这个框架
首先,按照咱们常规的方式先模拟,咱们先将一套基本流程走下来
/** * 帐户业务层接口 */
public interface AccountService {
void addAccount();
}
/** * 帐户业务层实现类 */
public class AccountServiceImpl implements AccountService {
private AccountDao accountDao = new AccountDaoImpl();
public void addAccount() {
accountDao.addAccount();
}
}
复制代码
/** * 帐户持久层接口 */
public interface AccountDao {
void addAccount();
}
/** * 帐户持久层实现类 */
public class AccountDaoImpl implements AccountDao {
public void addAccount() {
System.out.println("添加用户成功!");
}
}
复制代码
因为,咱们建立的Maven工程并非一个web工程,咱们也只是为了简单模拟,因此在这里,建立了一个 Client 类,做为客户端,来测试咱们的方法
public class Client {
public static void main(String[] args) {
AccountService as = new AccountServiceImpl();
as.addAccount();
}
}
复制代码
运行的结果,就是在屏幕上输出一个添加用户成功的字样
上面的这段代码,应该是比较简单也容易想到的一种实现方式了,可是它的耦合性倒是很高的,其中这两句代码,就是形成耦合性高的根由,由于业务层(service)调用持久层(dao),这个时候业务层将很大的依赖于持久层的接口(AccountDao)和实现类(AccountDaoImpl)
private AccountDao accountDao = new AccountDaoImpl();
AccountService as = new AccountServiceImpl();
复制代码
这种经过 new 对象的方式,使得不一样类之间的依赖性大大加强,其中一个类的问题,就会直接致使出现全局的问题,若是咱们将被调用的方法进行错误的修改,或者说删掉某一个类,执行的结果就是:
在编译期就出现了错误,而咱们做为一个开发者,咱们应该努力让程序在编译期不依赖,而运行时才能够有一些必要的依赖(依赖是不可能彻底消除的)
因此,咱们应该想办法进行解耦,要解耦就要使调用者和被调用者之间没有什么直接的联系,那么工厂模式就能够帮助咱们很好的解决这个问题
应该你们在 JavaWeb 或者 JavaSE的学习中,或多或少是有接触过工厂这个设计模式的,而工厂模式,咱们简单提一下,工厂就是在调用者和被调用者之间起一个链接枢纽的做用,调用者和被调用者都只与工厂进行联系,从而减小了二者之间直接的依赖(若是有一些迷茫的朋友,能够了解一下这种设计模式)
传统模式:
工厂模式:
具体怎么实现呢?在这里能够将 serivice 和 dao 均配置到配置文件中去(xml/properties),经过一个类读取配置文件中的内容,并使用反射技术建立对象,而后存起来,完成这个操做的类就是咱们的工厂
注:在这里咱们使用了 properties ,主要是为了实现方便,xml还涉及到解析的一些代码,相对麻烦一些,不过咱们下面要说的 Spring 就是使用了 xml作配置文件
accountService=cn.ideal.service.impl.AccountServiceImpl
accountDao=cn.ideal.dao.impl.AccountDaoImpl
复制代码
public class BeanFactory {
//定义一个Properties对象
private static Properties properties;
//使用静态代码块为Properties对象赋值
static {
try{
//实例化对象
properties = new Properties();
//获取properties文件的流对象
InputStream in = BeanFactory.class.getClassLoader().getResourceAsStream("bean.properties");
properties.load(in);
}catch (Exception e){
throw new ExceptionInInitializerError("初始化properties失败");
}
}
}
复制代码
简单的解释一下这部分代码(固然还没写完):首先就是要将配置文件中的内容读入,这里经过类加载器的方式操做,读入一个流文件,而后从中读取键值对,因为只须要执一次,因此放在静态代码块中,又由于 properties 对象在后面的方法中还要用,因此写在成员的位置
接着在 BeanFactory 中继续编写一个 getBean 方法其中有两句核心代码的意义就是:
public static Object getBean(String beanName){
Object bean = null;
try {
//根据key获取value
String beanPath = properties.getProperty(beanName);
bean = Class.forName(beanPath).newInstance();
}catch (Exception e){
e.printStackTrace();
}
return bean;
}
复制代码
public class Client {
public static void main(String[] args) {
AccountService as = (AccountService)BeanFactory.getBean("accountService");
as.addAccount();
}
}
复制代码
当咱们按照一样的操做,删除掉被调用的 dao 的实现类,能够看到,这时候编译期错误已经消失了,而报出来的只是一个运行时异常,这样就解决了前面所思考的问题
咱们应该努力让程序在编译期不依赖,而运行时才能够有一些必要的依赖(依赖是不可能彻底消除的)
为何使用工厂模式替代了 new 的方式?
打个比方,在你的程序中,若是一段时间后,你发如今你 new 的这个对象中存在着bug或者不合理的地方,或者说你甚至想换一个持久层的框架,这种状况下,没办法,只能修改源码了,而后从新编译,部署,可是若是你使用工厂模式,你只须要从新将想修改的类,单独写好,编译后放到文件中去,只须要修改一下配置文件就能够了
我分享下我我的精简下的理解就是:
【new 对象依赖的是具体事物,而不 new 则是依赖抽象事物】
Break it down:
到这里,彷佛还不错,不过咱们的程序还可以继续优化! 来分析一下:
首先在测试中,多打印几回,工厂所建立出的对象,咱们写个for循环打印下
for(int i = 0; i < 4; i++){
AccountService as = (AccountService)BeanFactory.getBean("accountService");
System.out.println(as);
}
复制代码
看下结果:特别显眼的四次输出,咱们的问题也就出来了,我所建立的4个对象是不一样的,也就是说,每一次调用,都会实例化一个新的对象,这也叫作多例
这有什么问题吗?
①:屡次建立对象的代价就是消耗性能,致使效率会低一些
②:相比较单例,jvm会回收较多的垃圾
③:获取速度比单例慢,由于单例除了第一次,其后都是从缓存中获取
因此,咱们要试着将它改为单例的,单例从表现上来看,咱们查询到的对象都应该是一个
前面咱们每一次调用都要将类进行 newInstance(),也就是实例化,想要再也不建立新的对象,只须要将咱们第一次建立的对象,在建立后就存到一个集合(容器)中,因为咱们有查询的需求因此在 Map 和 List 中选择了 Map
简单解读一下:
首先在成员位置定义一个 Map,称做beans,至于实例化就不说了
经过 keys 方法,取出全部的 配置中全部的key,而后进行遍历出每个key
经过每一个 key 从配置中取出对应的 value 在这里就是对应类的全类名
将每一个取出的 value,使用反射建立出对象 obj
将 key 与 obj 存入Map容器
在 getBean 方法中只须要从 Map中取就能够了
public class BeanFactory {
//定义一个Properties对象
private static Properties properties;
//定义Map,做为存放对象的容器
private static Map<String, Object> beans;
//使用静态代码块为Properties对象赋值
static {
try {
//实例化对象
properties = new Properties();
//获取properties文件的流对象
InputStream in = BeanFactory.class.getClassLoader().getResourceAsStream("bean.properties");
properties.load(in);
//实例化容器
beans = new HashMap<String, Object>();
//取出全部key
Enumeration keys = properties.keys();
//遍历枚举
while (keys.hasMoreElements()) {
String key = keys.nextElement().toString();
//根据获取到的key获取对应value
String beanPath = properties.getProperty(key);
//反射创对象
Object obj = Class.forName(beanPath).newInstance();
beans.put(key, obj);
}
} catch (Exception e) {
throw new ExceptionInInitializerError("初始化properties失败");
}
}
public static Object getBean(String beanName) {
return beans.get(beanName);
}
}
复制代码
测试结果已经变成了单例的
单例一个很明显的问题,就是在并发状况下,可能会出现线程安全问题
由于因为单例状况下,对象只会被实例化一次,这也就说,全部请求都会共享一个 bean 实例,若一个请求改变了对象的状态,同时对象又处理别的请求,以前的请求形成的对象状态改变,可能会影响在操做时,对别的请求作了错误的处理
举个简单的例子帮助理解:
修改一下 dao 的实现类
public class AccountDaoImpl implements AccountDao {
//定义一个类成员
private int i = 1;
public void addAccount() {
System.out.println("添加用户成功!");
System.out.println(i);
i++;
}
}
复制代码
测试中依旧是哪一个循环,不过此次执行一下 addAccount() 方法
经过测试能够看到,单例的状况下,我在dao实现类中 添加了一个类成员 i,而后在方法中对其进行累加并输出操做,每个值都会被修改,这就出现了咱们担忧的问题
可是回顾咱们从前的编程习惯,彷佛咱们从未在 service 或 dao 中书写过 类成员,并在方法中对其进行操做,咱们通常都是在方法内定义,而这种习惯,也保证了咱们如今不会出现这样的问题
将变量定义到方法内
public class AccountDaoImpl implements AccountDao {
public void addAccount() {
int i = 1;
System.out.println("添加用户成功!");
System.out.println(i);
i++;
}
}
复制代码
测试一下
好了这样就没有问题了!
讲这么多,就是为了配合 Spring 的学习,前面咱们使用工厂模式对传统的程序进行了改造,程序再也不与众多资源等直接联系,而是经过工厂进行提供分配,这种被动接受获取对象的方式就是控制反转,也是它的核心之一,如今就能够开始进入正题了:
如今咱们就正式开始进入到 Spring 框架的学习中去,而在这部分,并非说作增删改查,而是经过 Spring 解决依赖的问题,这也就是咱们上面众多铺垫内容的缘由
因为咱们使用的是 maven 建立出一个普通的 java 工程就能够了,不须要建立 java web工程,固然若是不是使用 maven的朋友能够去官网下载jar包 将须要的 bean context core spel log4j 等放到lib中
仍是使用前面这个帐户的案例,具体的一些接口等等仍是用前面的 将第二大点的时候,我已经贴出来了
首先在 maven 中导入须要内容的坐标
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>cn.ideal</groupId>
<artifactId>spring_02_ioc</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.0.2.RELEASE</version>
</dependency>
</dependencies>
</project>
复制代码
<?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.xsd">
</beans>
复制代码
<!--把对象的建立交给spring来管理-->
<bean id="accountService" class="cn.ideal.service.impl.AccountServiceImpl"></bean>
<bean id="accountDao" class="cn.ideal.dao.impl.AccountDaoImpl"></bean>
复制代码
为何用这些,等运行后说,先让程序跑起来
public class Client {
public static void main(String[] args) {
//获取核心容器
ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
//根据id后去Bean对象,下面两种方式均可以
AccountService as = (AccountService)ac.getBean("accountService");
AccountDao ad = ac.getBean("accountDao", AccountDao.class);
System.out.println(as);
System.out.println(ad);
}
}
复制代码
程序运行起来是没有问题的,到这里一个入门例程就跑起来了
首先咱们来分析一下在调用时的一些内容,测试时,第一个内容,就是获取核心容器,经过了一个 ApplicationContext 进行接收,那么它是什么呢
首先看一下这个图
能够看到 BeanFactory 才是 Spring 管理 Bean 的顶级接口,它提供了实例化对象和取出对象的功能,可是因为BeanFactory的简单与一些局限性,有时候并非很适合于大型企业级的开发,所以,Spring提供了一个新的内容也就是 ApplicationContext:它是一个更加高级的容器,而且功能更加分丰富
在使用时最明显的一个区别就是:二者建立对象的时间点不同
ApplicationContext:单例对象适用采用此接口
BeanFactory:多例对象适合
下面是使用 BeanFactory 进行测试的代码,不过有一些方法已通过时了,给你们参考使用,可使用打断点的方式进行测试
Resource resource = new ClassPathResource("bean.xml");
BeanFactory factory = new XmlBeanFactory(resource);
AccountService as = (AccountService)factory.getBean("accountService");
System.out.println(as);
复制代码
查看 ApplicationContext 的实现类咱们要说的就是红框中的几个
ClassPathXmlApplicationContext:能够加载类路径下的配置文件,固然配置文件必须在类路径下(用的更多)
复制代码
AnnotationConfigApplicationContext:读取注解建立容器
复制代码
咱们因为这篇文章中并无说注解的问题,因此咱们先只看前两个
ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
复制代码
ApplicationContext ac = new FileSystemXmlApplicationContext("D:\\bean.xml");
复制代码
配置文件中的bean标签,它的做用是配置对象,方便 spring进行建立,介绍一下其中的经常使用属性
id:对象的惟一标识
class:指定要建立的对象的全限定类名
scope:指定对象的做用范围
singleton:单例的(默认)
prototype:多例的
request:WEB 项目中,Spring 建立 Bean 对象,将对象存入到 request 域中
session:WEB 项目中,Spring 建立 Bean 的对象,将对象存入到 session 域中
global session:WEB 项目中, Portlet 环境使用,若没有 Portlet 环境那么globalSession 至关于 session
init-method:指定类中的初始化方法名称
destroy-method:指定类中销毁方法名称
在Spring 中默认是单例的,这也就是咱们在前面的自定义工厂过程当中所作的,在Spring中还须要说明,补充一下:
做用范围:
生命周期:
<bean id="accountService" class="cn.ideal.service.impl.AccountServiceImpl"></bean>
复制代码
在某些状况下,例如咱们想要使用一些别人封装好的方法,颇有可能存在于jar包中,而且都是 一些字节码文件,咱们是没有修改的权利了,那这时候咱们想要使用还可使用下面两种方法
②:Spring 实例工厂
模拟一个实例工厂,建立业务层实现类,这种状况下,必须先有工厂实例对象,才能调用方法
public class InstanceFactory {
public AccountService createAccountService(){
return new AccountServiceImpl();
}
}
复制代码
<bean id="instancFactory" class="cn.ideal.factory.InstanceFactory"></bean>
<bean id="accountService"factory-bean="instancFactory"factory-method="createAccountService"></bean>
复制代码
public class StaticFactory {
public static IAccountService createAccountService(){
return new AccountServiceImpl();
}
}
复制代码
<bean id="accountService"class="cn.ideal.factory.StaticFactory" factory-method="createAccountService"></bean>
复制代码
控制反转(IoC)是一种思想,而依赖注入(Dependency Injection)则是实现这种思想的方法
其实泛概念上二者是接近的,能够简单的理解为一个概念的不一样角度描述
咱们前面写程序的时候,经过控制反转,使得 Spring 能够建立对象,这样减低了耦合性,可是每一个类或模块之间的依赖是不可能彻底消失的,而这种依赖关系,咱们能够彻底交给 spring 来维护
这种注入方式有三种,先来看第一种
这一种的前提就是:类中必须提供一个和参数列表相对应的构造函数
看个例子就清楚了
咱们就在 service 中建立几个成员,而后给出其对应的带参构造,以及添加一个方法
/** * 帐户业务层实现类 */
public class AccountServiceImpl implements AccountService {
private String username;
private Integer age;
private Date birthday;
public AccountServiceImpl(String username, Integer phone, Date birthday) {
this.username = username;
this.age = phone;
this.birthday = birthday;
}
public void addAccount() {
System.out.println("username: " + username
+ ", phone: " + age
+ ", birthday: " + birthday);
}
}
复制代码
添加配置,这里先运行,再解释
<bean id="accountService" class="cn.ideal.service.impl.AccountServiceImpl">
<constructor-arg name="username" value="汤姆"></constructor-arg>
<constructor-arg name="phone" value="21"></constructor-arg>
<constructor-arg name="birthday" ref="nowdt"></constructor-arg>
</bean>
<bean id="nowdt" class="java.util.Date"></bean>
复制代码
测试后,成功的获取到了这些值,而且根据方法内的格式,打印到了屏幕上
username: 汤姆, phone: 21, birthday: Sat Feb 15 16:09:00 CST 2020
看完这个例子,好像有点明白了,上面所作的不就是,使用类的构造函数给成员变量进行赋值,但特别的是,这里是经过配置,使用 Spring 框架进行注入
来讲一下所涉及到的标签:
顾名思义,咱们将前面的构造函数先注释掉,而后补充成员变量的 set 方法
在配置的时候,须要修改
<bean id="accountService"class="cn.ideal.service.impl.AccountServiceImpl">
<property name="username" value="汤姆"></property>
<property name="age" value="21"></property>
<property name="birthday" ref="nowdt"></property>
</bean>
<bean id="nowdt" class="java.util.Date"></bean>
复制代码
在这里,还有一种方式就是使用 p名称空间注入数据 (本质仍是set)
头部中须要修改引入这一句
xmlns:p="http://www.springframework.org/schema/p"
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:p="http://www.springframework.org/schema/p" 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.xsd">
<bean id="accountService" class="cn.ideal.service.impl.AccountServiceImpl" p:name="汤姆" p:age="21" p:birthday-ref="nowdt"/>
<bean id="nowdt" class="java.util.Date"></bean>
</beans>
复制代码
为了演示这些方式,咱们在成员中将常见的一些集合都写出来,而后补充其 set 方法
private String[] strs;
private List<String> list;
private Set<String> set;
private Map<String,String> map;
private Properties props;
复制代码
在配置中也是很简单的,只须要按照下列格式写标签就能够了,能够本身测试一下
<bean id="accountService" class="cn.ideal.service.impl.AccountServiceImpl">
<property name="strs">
<array>
<value>张三</value>
<value>李四</value>
<value>王五</value>
</array>
</property>
<property name="list">
<list>
<value>张三</value>
<value>李四</value>
<value>王五</value>
</list>
</property>
<property name="set">
<set>
<value>张三</value>
<value>李四</value>
<value>王五</value>
</set>
</property>
<property name="map">
<map>
<entry key="name" value="张三"></entry>
<entry key="age" value="21"></entry>
</map>
</property>
<property name="props">
<props>
<prop key="name">张三</prop>
<prop key="age">21</prop>
</props>
</property>
</bean>
复制代码
写到这里,这部分Spring框架的入门内容就结束了,先简单提了下 Spring 框架的基本知识,一个是因为为了能让你们详细的理解 Spring 为咱们带来的好处,二呢是我写文章的出发点,是想让全部刚接触 Spring 框架的人均可以看得懂,因此首先,先从耦合的一些概念,而后分析到咱们传统程序中存在的耦合问题,接着用单例改进这个程序,实际上这都是为了向 Spring 靠近,接下来就是真正的上手,使用Spring框架,了解了其 控制反转(IoC)和依赖注入(DI)技术 ,不是很复杂,主要是想用一种按部就班的方式,一步一步入门,不知不觉写了都快1w字了
很是但愿能给你们提供一些帮助!
或许你掉进了黑暗,我惟一能作的,就是走进黑暗,陪你慢慢走出来
若是文章中有什么不足,欢迎你们留言交流,感谢朋友们的支持!
若是能帮到你的话,那就来关注我吧!若是您更喜欢微信文章的阅读方式,能够关注个人公众号
在这里的咱们素不相识,却都在为了本身的梦而努力 ❤
一个坚持推送原创开发技术文章的公众号:理想二旬不止