spring是J2EE应用程序框架,是轻量级的IoC和AOP的容器框架,主要是针对javaBean的生命周期进行管理的轻量级容器,可以单独使用,也可以和Struts框架,ibatis框架等组合使用。
Spring 体系结构:
- 核心容器
核心容器由核心,Bean,上下文和表达式语言模块组成,它们的细节如下:
核心模块提供了框架的基本组成部分,包括 IoC 和依赖注入功能。
Bean 模块提供 BeanFactory,它是一个工厂模式的复杂实现。
上下文模块建立在由核心和 Bean 模块提供的坚实基础上,它是访问定义和配置的任何对象的媒介。ApplicationContext 接口是上下文模块的重点。
表达式语言模块在运行时提供了查询和操作一个对象图的强大的表达式语言。
- 数据访问/集成
数据访问/集成层包括 JDBC,ORM,OXM,JMS 和事务处理模块,它们的细节如下:
JDBC 模块提供了删除冗余的 JDBC 相关编码的 JDBC 抽象层。
ORM 模块为流行的对象关系映射 API,包括 JPA,JDO,Hibernate 和 iBatis,提供了集成层。
OXM 模块提供了抽象层,它支持对 JAXB,Castor,XMLBeans,JiBX 和 XStream 的对象/XML 映射实现。
Java 消息服务 JMS 模块包含生产和消费的信息的功能。
事务模块为实现特殊接口的类及所有的 POJO
- 支持编程式和声明式事务管理。
Web
Web 层由 Web,Web-MVC,Web-Socket 和 Web-Portlet 组成,它们的细节如下:
Web 模块提供了基本的面向 web 的集成功能,例如多个文件上传的功能和使用 servlet 监听器和面向 web 应用程序的上下文来初始化 IoC 容器。
Web-MVC 模块包含 Spring 的模型-视图-控制器(MVC),实现了 web 应用程序。
Web-Socket 模块为 WebSocket-based 提供了支持,而且在 web 应用程序中提供了客户端和服务器端之间通信的两种方式。
Web-Portlet 模块提供了在 portlet 环境中实现 MVC,并且反映了 Web-Servlet 模块的功能。
- 其他
还有其他一些重要的模块,像 AOP,Aspects,Instrumentation,Web 和测试模块,它们的细节如下:
AOP 模块提供了面向方面的编程实现,允许你定义方法拦截器和切入点对代码进行干净地解耦,它实现了应该分离的功能。
Aspects 模块提供了与 AspectJ 的集成,这是一个功能强大且成熟的面向切面编程(AOP)框架。
Instrumentation 模块在一定的应用服务器中提供了类 instrumentation 的支持和类加载器的实现。
Messaging 模块为 STOMP 提供了支持作为在应用程序中 WebSocket 子协议的使用。它也支持一个注解编程模型,它是为了选路和处理来自 WebSocket 客户端的 STOMP 信息。
测试模块支持对具有 JUnit 或 TestNG 框架的 Spring 组件的测试。
Hello World 实例
javaBean
public class HelloWorld {
private String message;
public void setMessage(String message){
this.message = message;
}
public void getMessage(){
System.out.println("Your Message : " + message);
}
}
XML配置文件
测试类
public class MainApp {
public static void main(String[] args) {
ApplicationContext context =
new ClassPathXmlApplicationContext("Beans.xml");
HelloWorld obj = (HelloWorld) context.getBean("helloWorld");
obj.getMessage();
}
}
IOC 容器
Spring 容器是 Spring 框架的核心。容器将创建对象,把它们连接在一起,配置它们,并管理他们的整个生命周期从创建到销毁。Spring 容器使用依赖注入(DI)来管理组成一个应用程序的组件。这些对象被称为 Spring Beans
序号 | 容器 & 描述 |
---|---|
Spring BeanFactory 容器 | 它是最简单的容器,给 DI 提供了基本的支持,它用 org.springframework.beans.factory.BeanFactory 接口来定义。BeanFactory 或者相关的接口,如 BeanFactoryAware,InitializingBean,DisposableBean,在 Spring 中仍然存在具有大量的与 Spring 整合的第三方框架的反向兼容性的目的 |
Spring ApplicationContext 容器 | 该容器添加了更多的企业特定的功能,例如从一个属性文件中解析文本信息的能力,发布应用程序事件给感兴趣的事件监听器的能力。该容器是由 org.springframework.context.ApplicationContext 接口定义 |
Spring 提供了以下两种不同类型的容器。
序号 | 容器 & 描述 |
---|---|
Spring BeanFactory 容器 | 它是最简单的容器,给 DI 提供了基本的支持,它用 org.springframework.beans.factory.BeanFactory 接口来定义。BeanFactory 或者相关的接口,如 BeanFactoryAware,InitializingBean,DisposableBean,在 Spring 中仍然存在具有大量的与 Spring 整合的第三方框架的反向兼容性的目的 |
Spring ApplicationContext 容器 | 该容器添加了更多的企业特定的功能,例如从一个属性文件中解析文本信息的能力,发布应用程序事件给感兴趣的事件监听器的能力。该容器是由 org.springframework.context.ApplicationContext 接口定义 |
实例代码
XmlBeanFactory factory = new XmlBeanFactory(new ClassPathResource("Beans.xml"));
HelloWorld obj = (HelloWorld) factory.getBean("helloWorld");
obj.getMessage();
最常被使用的 ApplicationContext 接口实现:
FileSystemXmlApplicationContext:该容器从 XML 文件中加载已被定义的 bean。在这里,你需要提供给构造器 XML 文件的完整路径
ClassPathXmlApplicationContext:该容器从 XML 文件中加载已被定义的 bean。在这里,你不需要提供 XML 文件的完整路径,只需正确配置 CLASSPATH 环境变量即可,因为,容器会从 CLASSPATH 中搜索 bean 配置文件。
WebXmlApplicationContext:该容器会在一个 web 应用程序的范围内加载在 XML 文件中已被定义的 bean。
Bean 的作用域
Bean 对象创建的时机
默认是随着容器创建,可以使用 lazy-init=true(在调用 getBean 创建)延迟创建也可以用
批量延迟创建
Spring 框架支持以下五个作用域,如果你使用 web-aware ApplicationContext 时,其中三个是可用的。
作用域 | 描述 |
---|---|
singleton | 该作用域将 bean 的定义的限制在每一个 Spring IoC 容器中的一个单一实例(默认) |
prototype | 该作用域将单一 bean 的定义限制在任意数量的对象实例。 |
request | 该作用域将 bean 的定义限制为 HTTP 请求。只在 web-aware Spring ApplicationContext 的上下文中有效 |
session | 该作用域将 bean 的定义限制为 HTTP 会话。 只在web-aware Spring ApplicationContext的上下文中有效 |
global-session | 该作用域将 bean 的定义限制为全局 HTTP 会话。只在 web-aware Spring ApplicationContext 的上下文中有效 |
Bean 的生命周期
为了定义安装和拆卸一个 bean,我们只要声明带有 init-method 和/或 destroy-method 参数(,仅适用于 singleton 模式
) 。init-method 属性指定一个方法,在实例化 bean 时,立即调用该方法。同样,destroy-method 指定一个方法,只有从容器中移除 bean 之后,才能调用该方法。
Bean 后置处理器
BeanPostProcessor 接口定义回调方法,你可以实现该方法来提供自己的实例化逻辑,依赖解析逻辑等。你也可以在 Spring 容器通过插入一个或多个 BeanPostProcessor 的实现来完成实例化,配置和初始化一个bean之后实现一些自定义逻辑回调方法。
HelloWorld.java
public class HelloWorld {
private String message;
public void setMessage(String message){
this.message = message;
}
public void getMessage(){
System.out.println("Your Message : " + message);
}
public void init(){
System.out.println("Bean is going through init.");
}
public void destroy(){
System.out.println("Bean will destroy now.");
}
}
InitHelloWorld.java
public class InitHelloWorld implements BeanPostProcessor {
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("BeforeInitialization : " + beanName);
return bean; // you can return any other object as well
}
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("AfterInitialization : " + beanName);
return bean; // you can return any other object as well
}
}
MainApp.java 文件的内容。在这里,你需要注册一个在 AbstractApplicationContext 类中声明的关闭 hook 的 registerShutdownHook() 方法。它将确保正常关闭,并且调用相关的 destroy 方法。
public class MainApp {
public static void main(String[] args) {
AbstractApplicationContext context = new ClassPathXmlApplicationContext("Beans.xml");
HelloWorld obj = (HelloWorld) context.getBean("helloWorld");
obj.getMessage();
context.registerShutdownHook();
}
}
Beans.xml
Bean 定义继承
Beans.xml
HelloWorld.java
public class HelloWorld {
private String message1;
private String message2;
public void setMessage1(String message){
this.message1 = message;
}
public void setMessage2(String message){
this.message2 = message;
}
public void getMessage1(){
System.out.println("World Message1 : " + message1);
}
public void getMessage2(){
System.out.println("World Message2 : " + message2);
}
}
HelloIndia.java
public class HelloIndia {
private String message1;
private String message2;
private String message3;
public void setMessage1(String message){
this.message1 = message;
}
public void setMessage2(String message){
this.message2 = message;
}
public void setMessage3(String message){
this.message3 = message;
}
public void getMessage1(){
System.out.println("India Message1 : " + message1);
}
public void getMessage2(){
System.out.println("India Message2 : " + message2);
}
public void getMessage3(){
System.out.println("India Message3 : " + message3);
}
}
MainApp.java
public class MainApp {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("Beans.xml");
HelloWorld objA = (HelloWorld) context.getBean("helloWorld");
objA.getMessage1();
objA.getMessage2();
HelloIndia objB = (HelloIndia) context.getBean("helloIndia");
objB.getMessage1();
objB.getMessage2();
objB.getMessage3();
}
}
Bean 定义模板
你可以创建一个 Bean 定义模板,不需要花太多功夫它就可以被其他子 bean 定义使用。在定义一个 Bean 定义模板时,你不应该指定类的属性,而应该指定带 true 值的抽象属性
DI依赖注入
序号 | 依赖注入类型 & 描述 |
---|---|
Constructor-based dependency injection | 当容器调用带有多个参数的构造函数类时,实现基于构造函数的 DI,每个代表在其他类中的一个依赖关系 |
Setter-based dependency injection | 基于 setter 方法的 DI 是通过在调用无参数的构造函数或无参数的静态工厂方法实例化 bean 之后容器调用 beans 的 setter 方法来实现的 |
代码实例
public class User {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
Beans.xml
yudesong
注入内部 Beans
TextEditor.java
public class TextEditor {
private SpellChecker spellChecker;
// a setter method to inject the dependency.
public void setSpellChecker(SpellChecker spellChecker) {
System.out.println("Inside setSpellChecker." );
this.spellChecker = spellChecker;
}
// a getter method to return spellChecker
public SpellChecker getSpellChecker() {
return spellChecker;
}
public void spellCheck() {
spellChecker.checkSpelling();
}
}
SpellChecker.java
public class SpellChecker {
public SpellChecker(){
System.out.println("Inside SpellChecker constructor." );
}
public void checkSpelling(){
System.out.println("Inside checkSpelling." );
}
}
Beans.xml
注入集合
元素 | 描述 |
---|---|
它有助于连线,如注入一列值,允许重复 | |
它有助于连线一组值,但不能重复 | |
它可以用来注入名称-值对的集合,其中名称和值可以是任何类型 | |
它可以用来注入名称-值对的集合,其中名称和值都是字符串类型 |
Spring 提供了四种类型的集合的配置元素
元素 | 描述 |
---|---|
它有助于连线,如注入一列值,允许重复 | |
它有助于连线一组值,但不能重复 | |
它可以用来注入名称-值对的集合,其中名称和值可以是任何类型 | |
它可以用来注入名称-值对的集合,其中名称和值都是字符串类型 |
List addressList;
Set addressSet;
Map addressMap;
Properties addressProp;
INDIA
Pakistan
USA
USA
INDIA
Pakistan
USA
USA
INDIA
Pakistan
USA
USA
//处理NULL
//处理空字符串
AOP技术
Aspect Oriented Programming 面向方面编程戒面向切面编程
AOP 关注点是共同处理,可以通过配置将其作用到某一个戒多个目标对象上。好处是实现组件重复
利用,改善程序结构,提高灵活性。将共通组件不目标对象解耦。
AOP 相关概念
-
- Aspect 切面(方面)
指的是共通业务处理,可以切入到多个目标对象,可多次使用
- Aspect 切面(方面)
-
- JoinPoint 连接点
指的是切面组件在目标对象上作用的位置,例如:方法上戒者发生异常
- JoinPoint 连接点
-
- Pointcut 切入点
切入点是连接点的集合,采用表达式指定
- Pointcut 切入点
-
- Target Object 目标对象
-
- Advice 通知
指的是切面组件在连接点上执行的劢作。例如:在方法调用前、方法调用后、方法调用前后等
- Advice 通知
-
- AutoProxy 劢态代理
采用了 AOP之后,容器返回的对象是代理对象。用户在使用时,由代理对象调用切面组件和目标对象的功能
a. 目标对象有接口采用 JDK 代理、
b. 目标对象没有接口采用 CGLIB 代理
- AutoProxy 劢态代理
编写spring的配置文件applicationContext.xml
HelloWordImpl.java
public interface HelloWord {
public int sayHello(int num);
}
@Component
public class HelloWordImpl implements HelloWord{
public int sayHello(int num){
System.out.println("hello word");
return 100/num;
}
}
SpringAOP注释的类型
- @Before 前置通知 在方法执行前执行
- @After 后置通知 在方法执行后执行
- @AfterThrowing 异常通知 在方法抛出异常之后执行
- @AfterReturning 返回通知 在方法返回结果之后执行
- @Around 环绕通知 环绕着方法执行
@Component
@Aspect
public class HelloWordAspect {
@Before(value="execution(* test.Spring.AOP.HelloWord.sayHello(..))")
public void beforeMethod(JoinPoint jp){
String methodName = jp.getSignature().getName();
System.out.println(methodName);
System.out.println("before method execute,args are "+Arrays.toString(jp.getArgs()));
}
@After("execution(* test.Spring.AOP.HelloWord.sayHello(..))")
public void afterMethod(JoinPoint jp){
System.out.println("after method execute,args are "+Arrays.toString(jp.getArgs()));
}
@AfterThrowing(value="execution(* test.Spring.AOP.HelloWord.sayHello(..))",throwing="ex")
public void afterThrow(Exception ex){
System.out.println("afterThrow"+ex.getMessage());
}
@AfterReturning(value="execution(* test.Spring.AOP.HelloWord.sayHello(..))",returning="result")
public void afterReturn(Object result){
System.out.println("the result is "+result);
}
}
主函数
public class Main {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContextForAOP.xml");
HelloWord hw = (HelloWord) context.getBean("helloWordImpl");
hw.sayHello(10);
}
}
使用Around环绕通知切面类实现类似效果
@Component
@Aspect
public class HelloWordAspectAround {
@Around(value="execution(* test.Spring.AOP.HelloWord.sayHello(..)))")
public Object aroundMethod(ProceedingJoinPoint pjp){
Object result = null;
String methodName = pjp.getSignature().getName();
try {
result = pjp.proceed();
System.out.println("the result is "+result);
} catch (Throwable e) {
System.out.println("Exception occurs : "+e.getMessage());
throw new RuntimeException(e);
}
System.out.println(methodName+" end");
return result;
}
}
更多内容
1. 深入浅出Spring IOC-1
2. 深入浅出Spring IOC-2
3. 深入浅出Spring IOC-3
4. 深入浅出Spring IOC-4
5. 深入浅出Spring AOP