1. 什么是spring,它能够做什么?
Spring是一个开源框架,它由Rod Johnson创建。它是为了解决企业应用开发的复杂性而创建的。Spring使用基本的JavaBean来完成以前只可能由EJB完成的事情。然而,Spring的用途不仅限于服务器端的开发。从简单性、可测试性和松耦合的角度而言,任何Java应用都可以从Spring中受益。
Spring项目出发点:
- 目的:提供一种贯穿始终的解决方面,将各种专用框架整合成一个连贯的整体框架,简化企业级应用的开发(有点像粘合剂)
- 鼓励最佳实践: 例如spring将“针对接口编程”的成本降到了最小
- 非侵入性: 应用对象尽量避免依赖框架,IoC和AOP是避免依赖的关键技术
- 统一配置: 好的框架应该让应用配置灵活且统一
- 易于测试: 使单元测试尽可能简单
- 可扩展:
简单来说,Spring是一个轻量级的控制反转(IoC)和面向切面(AOP)的容器框架。
2. 什么是控制反转(或依赖注入)
控制反转(IoC=Inversion of Control)IoC,用白话来讲,就是由容器控制程序之间的(依赖)关系,而非传统实现中,由程序代码直接操控。这也就是所谓“控制反转”的概念所在:(依赖)控制权由应用代码中转到了外部容器,控制权的转移,是所谓反转。
IoC还有一个另外的名字:“依赖注入 (DI=Dependency Injection)” ,即由容器动态的将某种依赖关系注入到组件之中。
3. AOP的关键概念
- 连接点(Joinpoint):程序执行过程中明确的点,如方法的调用,或者异常的抛出.
- 目标(Target):被通知(被代理)的对象
- 通知(Advice):在某个特定的连接点上执行的动作,同时Advice也是程序代码的具体实现,例如一个实现日志记录的代码(通知有些书上也称为处理)
- 代理(Proxy):将通知应用到目标对象后创建的对象(代理=目标+通知),请注意:只有代理对象才有AOP功能,而AOP的代码是写在通知的方法里面的
- 切入点(Pointcut):多个连接点的集合,定义了通知应该应用到那些连接点。(也将Pointcut理解成一个条件 ,此条件决定了容器在什么情况下将通知和目标组合成代理返回给外部程序)
- 适配器(Advisor):适配器=通知(Advice)+切入点(Pointcut)
4. 示例
4.1 创建工程
创建一个web工程,并转换为web3.1, 详细步骤可参见“maven”课件
4.2 pom文件
依赖配置如下:
<properties> <hibernate.version>5.2.12.Final</hibernate.version> <mysql.driver.version>5.1.44</mysql.driver.version> <spring.version>5.2.6.RELEASE</spring.version> <struts2.version>2.5.13</struts2.version> <slf4j.version>1.7.7</slf4j.version> <log4j.version>2.9.1</log4j.version> <disruptor.version>3.2.0</disruptor.version> <junit.version>4.12</junit.version> <servlet.version>4.0.1</servlet.version> <jstl.version>1.2</jstl.version> <standard.version>1.1.2</standard.version> <tomcat-jsp-api.version>8.5.20</tomcat-jsp-api.version> </properties> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <scope>test</scope> </dependency> <!-- spring 相关 --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-orm</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aop</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aspects</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-beans</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>${spring.version}</version> </dependency> <!-- 数据库驱动 --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>${mysql.driver.version}</version> </dependency> <!--4. log配置:Log4j2 + Slf4j --> <!-- slf4j核心包 --> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>${slf4j.version}</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>jcl-over-slf4j</artifactId> <version>${slf4j.version}</version> <scope>runtime</scope> </dependency> <!--用于与slf4j保持桥接 --> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-slf4j-impl</artifactId> <version>${log4j.version}</version> <exclusions> <exclusion> <artifactId>slf4j-api</artifactId> <groupId>org.slf4j</groupId> </exclusion> </exclusions> </dependency> <!--核心log4j2jar包 --> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-api</artifactId> <version>${log4j.version}</version> </dependency> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-core</artifactId> <version>${log4j.version}</version> </dependency> <!--web工程需要包含log4j-web,非web工程不需要 --> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-web</artifactId> <version>${log4j.version}</version> <scope>runtime</scope> </dependency> <!--需要使用log4j2的AsyncLogger需要包含disruptor --> <dependency> <groupId>com.lmax</groupId> <artifactId>disruptor</artifactId> <version>${disruptor.version}</version> </dependency> <!--5. other --> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>${junit.version}</version> <scope>test</scope> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>${servlet.version}</version> <scope>provided</scope> </dependency> <!--6. jstl --> <dependency> <groupId>javax.servlet.jsp.jstl</groupId> <artifactId>jstl</artifactId> <version>${jstl.version}</version> </dependency> <dependency> <groupId>taglibs</groupId> <artifactId>standard</artifactId> <version>${standard.version}</version> </dependency> <!-- 7. jsp自定义标签依赖 (必须与tomcat的版本一致) --> <dependency> <groupId>org.apache.tomcat</groupId> <artifactId>tomcat-jsp-api</artifactId> <version>${tomcat-jsp-api.version}</version> <scope>provided</scope> </dependency> </dependencies>
注: 该依赖配置不仅包含了spring,同时也包含了hibernate,struts,mysql驱动等。
4.3 spring配置文件
<?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:aop="http://www.springframework.org/schema/aop" 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.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.xsd"> </beans>
4.4 示例代码
4.4.1 示例1
1) Student
public class Student { private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public String toString() { return "Demo [name=" + name + "]"; } }
2) spring.xml 配置文件
<bean id="demo" class="org.lisen.springdemo.model.Demo"> <property name="name"> <value>张三</value> </property> </bean>
配置文件说明:
- id:在容器中查找Bean的id(唯一、且不能以/开头)
- class:bean的完整类名
- name:在容器中查找Bean的名字(唯一、允许以/开头、允许多个值,多个值之间用逗号或空格隔开)
- scope:(singleton|prototype)默认是singleton
singleton: 单例模式, 在每个Spring IoC容器中一个bean定义对应一个对象实例
prototype: 原型模式/多例模式, 一个bean定义对应多个对象实例 - parent:指定一个父bean(必须要有继承关系才行)
- abstract: 将一个bean定义成抽象bean(抽象bean是不能实例化的),抽象类一定要定义成抽象bean,非抽象类也可以定义成抽象bean
注: 在这里配置的name属性为简单的String属性,可以直接使用value进行配置。另外可以直接使用value设置的如下:
8基础数据+String+3个sql
java.util.Date
java.sql.Date
java.sql.Time
java.sql.Timestamp
3) 通过Spring的ApplicationContext获取Bean
public class SpringDemo { public static void main(String[] args) { ApplicationContext cxt = new ClassPathXmlApplicationContext("spring.xml"); Student demo = (Student)cxt.getBean("demo"); System.out.println(demo); } }
4.4.2 示例2 (abstract,parent示例)
1) Person
public class Student extends Person { private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public String toString() { return "Demo [name=" + name + "]"; } }