一、Spring的基本介绍
1、spring 介绍:
Spring 是一个轻量级的 DI/IoC 和 AOP 容器的开源框架
,致力于构建致力于构建轻量级的 JavaEE 应用
,简化应用开发
,本身涵盖了传统应用开发,还拓展到移动端,大数据等领域。
- Spring FrameWork: Spring 全家桶的核心, Spring 的其他产品都是基于Spring FrameWork 框架的。
2、spring 优势:
① Spring 能帮我们低侵入/低耦合地根据配置文件
创建及组装对象之间的依赖关系。
② Spring 面向切面编程能帮助我们无耦合的实现日志记录,性能统计,安全控制等。
③ Spring 能非常简单的且强大的声明式事务管理(通过配置完成事务,不用修改代码)。
④ Spring 提供了与第三方数据访问框架(如 Hibernate、JPA)无缝集成,且自己也提供了一套 JDBC 模板来方便数据库访问。
⑤ Spring 提供与第三方 Web(如 Struts1/2、JSF)框架无缝集成,且自己也提供了一套 Spring MVC 框架,来方便 Web 层搭建。
⑥ Spring 能方便的与如 Java Mail、任务调度、缓存框架等技术整合,降低开发难度。
3、spring FrameWork 框架的准备工作(框架压缩包、sts插件):
● spring 的官网:https://spring.io/
● 框架的压缩包下载地址:https://repo.spring.io/ui/native/libs-release-local/org/springframework/spring/
■ spring-frame 框架压缩文件介绍:
- docs:Spring开发的帮助文档
- libs:Spring核心组件的jar包、jar包的源码、jar包的文档
- schema: Spring 配置文件的schema约束文件。
● STS(Spring Tool Suite)工具下载地址:https://spring.io/tools
- 咱安装eclipse 版本的sts4 应用程序(sts4工具的话就是在eclipse基础上套上了有利于spring开发的组件等)
- 咱也可以安装 eclipse 版本的sts 插件:选择在线安装方式【步骤:help-》Eclipse Marketplace -》搜 Spring Tool即可】
4、Spring 思想 之 IoC 和 DI 思想:
✿ Spring 是一个DI容器或IoC容器
(DI和IoC 思想差不多)。掌握着创建对象和构建对象之间的依赖的控制权
。
● IoC:Inversion of Control(控制反转):
读作“反转控制”,更好理解,不是什么新技术,而是一种设计思想。 其本意是是将原本在程序中手动创建对象的控制权,交由 Spring 框架来管理。
- 反控:调用者只管负责从 Spring 容器中获取需要使用的对象,不关心对象的创建过程,也不关心该对象依赖对象的创建以及依赖关系的组装,也就是把创建对象的控制权反转给了 Spring 框架。
● DI:Dependency Injection(依赖注入):
读作“注入依赖”,更好理解,不是什么新技术,而是一种设计思想。
- 依赖注入:从字面上分析,IoC是指将对象的创建权,反转给了 Spring 容器; 具体是指 Spring 创建对象的过程中,将对象依赖属性(常量,对象,集合)通过配置设值给该对象。
二、Spring基本使用(Spring的开发步骤)
1、依赖jar包:
- spring-beans.jar
- spring-core.jar
- commons-logging.jar
2、配置(创建applicationContext.xml 配置文件):
- 使用sts工具:步骤【new -》Spring Bean Configuration File -》...】
- 安装sts工具默认是没有配带Spring Roo ,需要自己额外再安装一下Spring Roo 插件,右键文件才有 Spring Bean Configuration File
- 没安装sts 的时候,先创建一个普通的xml文件,然后到Spring Frame文档的Core 搜 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 https://www.springframework.org/schema/beans/spring-beans.xsd"> <!-- 通过配置的bean元素,告诉Spring的IoC容器,需要管理哪一个类的对象 --> <bean id="hello" class="com.shan.hello.Hello"> <!-- 通过property子元素,设置管理对象的属性的值 --> <property name="password" value="123"/> <property name="username" value="shan"/> </bean> </beans>
3、使用:
@Test void testIoC() throws Exception { Hello hello = null; //========================= //1、加载配置文件:从classpath路径去寻找配置文件,创建资源对象 Resource resource = new ClassPathResource("applicationContext.xml"); //2、创建IoC容器:创建spring的工厂对象(IoC容器对象) BeanFactory factory = new XmlBeanFactory(resource); //3、从Ioc容器获取对象:从spring IoC 容器(就是factory 工厂对象)中获取指定名称的对象 hello = (Hello)factory.getBean("hello"); //========================= hello.printUser(); }
■ 从例子,可以看出,spring不仅帮我们创建对象,还帮我们把对象需要的数据给设置进来(对象的属性依赖)
✿ 总结spring的开发步骤:
1、准备jar包
2、开发一个实例类
3、在applicationContext.xml 完成配置(注意约束xsd的内容可以到官网的Core那一章节进行拷贝)
4、启动Spring容器
5、从Spring容器中获取指定名称的bean对象
6、调用bean对象的方法
4、从Spring IoC容器中获取bean对象的方式【推荐使用:bean的名称+类型】
- 方式三(推荐): T getBean(String name, ClassrequiredType) 根据bean对象在容器中的 名称+类型 来获取
- hello = factory.getBean("hello", Hello.class);
//使用spring框架 @Test void testIoC() throws Exception { Hello hello = null; //========================= //1、加载配置文件:从classpath路径去寻找配置文件,创建资源对象 Resource resource = new ClassPathResource("applicationContext.xml"); //2、创建IoC容器:创建spring的工厂对象(IoC容器对象) BeanFactory factory = new XmlBeanFactory(resource); //3、从Ioc容器获取对象:从spring IoC 容器(就是factory 工厂对象)中获取指定名称的对象 //方式一: Object getBean(String name) 根据bean对象在容器中的名称来获取 // hello = (Hello)factory.getBean("hello"); //方式二: T getBean(Class<T> requiredType) 根据bean对象在容器中的类型来获取 // hello = factory.getBean(Hello.class); //方式三(推荐): T getBean(String name, Class<T> requiredType) 根据bean对象在容器中的 名称+类型 来获取 hello = factory.getBean("hello", Hello.class); //========================= hello.printUser(); }
5、spring 的基本配置
1、bean元素使用属性推荐id,而非name
2、元素:<import resource="com/shan/hello.xml"/> 用于引入spring的配置文件,相当于js中的元素 <javaScript src=""/> (推荐resource路径加上前缀 classpath)
□ 例如咱的hello.xml 全路径是:F/spring-base/src/com/shan/hello.xml
- 要注意,默认情况下,resource 是从 classpath 的跟路径寻找
- 可以使用前缀来定位文件的基础位置(就是加上前缀,常用的前缀是classpath),即
<import resource="classpath
:com/shan/hello.xml"/>
三、Spring的核心对象和管理bean的原理
1、Spring的核心对象:
- BeanFactory:是Spring的IoC容器(容器--管理对象的生命周期),生产 bean 对象的工厂,负责配置,创建和管理 bean。
- bean:被 Spring IoC 容器管理的对象称之为bean。
2、Spring IoC 容器如何知道它需要管理哪些对象:
---Spring IoC 容器通过读取配置文件
中的配置元数据,通过元数据对应用中的各个对象进行实例化及装配。
■ 元数据的配置有三种方式:
□ XML-based configuration (xml配置文件)
□ Annotation-based configuration (注解)
□ Java-based configuration (基于java代码)
3、Spring 管理bean的原理【底层是:反射(获取构造器实例对象)+内省机制(设置属性值)】:
① 通过 Resource 对象加载配置文件
② 解析配置文件,得到指定名称的 bean
③ 解析 bean 元素,id 作为 bean 的名字,class 用于反射得到 bean 的实例
- 注意:此时,bean 类必须存在一个
无参数构造器
(且该无参构造器和访问权限无关
);
④ 调用 getBean 方法的时候,从容器中返回对象实例;
■ 结论:就是把代码从 JAVA 文件中转移到了 XML 中。
/* 实体类Hello */ public class Hello { private String password; private String username; private Hello() {};//bean 类必须存在一个无参数构造器`(且该无参构造器和访问权限无关);可以是public,也可以是private public void setPassword(String password) { this.password = password; } public void setUsername(String username) { this.username = username; } public void printUser() { System.out.println("hello " + username + ", your password is " + password); } } /* 测试类 */ //简单模拟spring IoC容器的操作【管理对象的创建、管理对象的依赖关系,例如属性设置】 @Test void testIoCMock() throws Exception { String className = "com.shan.hello.Hello"; Hello hello = null; //================================ //实例Hello对象-反射常用的方法,调用Class类中的newInstance(); // Object obj = Class.forName(className).newInstance();//因为通过测试得知实体必须存在一个(与访问性无关的)构造器, //所以不是直接通过Class类的newInstance方法,而是先通过反射构建构造器Constructor,然后通过调用构造器Constructor的newInstance方法创建实例对象 //反射机制获取构造器 Class clazz = Class.forName(className); Constructor con = clazz.getDeclaredConstructor(); con.setAccessible(true);//设置构造器的可访问性 Object obj = con.newInstance(); hello = (Hello)obj; //内省机制操作javaBean属性 BeanInfo beanInfo = Introspector.getBeanInfo(clazz, Object.class); PropertyDescriptor[] pds = beanInfo.getPropertyDescriptors(); for (PropertyDescriptor pd : pds) { //当前的属性的属性名 String propertyName = pd.getName(); if("username".equals(propertyName)) { pd.getWriteMethod().invoke(hello,"shan"); }else if("password".equals(propertyName)) { pd.getWriteMethod().invoke(hello, "123"); } } hello.printUser(); }