Spring学习笔记-Spring之旅-01
使用Spring简化JAVA开发
Spring的四种关键策略:
●基于POJO的轻量级和最小侵入式编程;
●通过依赖注入(DI)和面向接口实现松耦合;
●基于切面(AOP)和惯例进行声明式编程。
●通过切面和模板减少样板式代码。
几乎Spring所做的任何事都可以追溯到上面的一条或多条策略。
依赖注入(DI)
传统编程经常需要多个对象相互协作完成某个功能,每个对象管理与自己相互协作的对象。
传统开发常见的例子
比如下面的例子
一个Amercan类,其中有一个sayHello方法。
一个DoSomething类,调用American类执行sayHello方法。
public class American{
public void sayHello(){
System.out.println("American say hello");
}
}
public class DoSomething{
private American american; //声明一个American类
DoSomething(){
this.american=new American(); //构造函数中初始化American类变量,这里与其紧耦合
}
public void do() {
person.sayHello();
}
}
public class Test {
public static void main(String[] args){
DoSomething doSomething=new DoSomething();
doSomething.sayHello();
}
}
可以发现在DoSomething类的构造函数自行创建了American类,与其紧密耦合在了一起,后期扩展、测试会面临很大困难。
改善后的例子:
public interface Person{
public void sayHello();
}
public class American implements{
public void sayHello(){
System.out.println("American say hello");
}
}
public class DoSomething{
private Person person; //声明一个Person接口
DoSomething(Person person){
this.person=person; //person通过构造参数传入
}
public void do() {
person.sayHello();
}
}
public class Test {
public static void main(String[] args){
DoSomething doSomething=new DoSomething(new American); //在构造函数中传入Perison实现
doSomething.sayHello();
}
}
现在使声明一个Person接口,在DoSomething声明一个Person接口,将Person接口的实例通过构造器参数传入,没有与任何实现产生耦合,只要实现了Person接口的类都能sayHello。
使用Spring装配bean和注入
Spring有多中装配bean的方式,以下为2种常用的方式:
●XMl
●注解
以下以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"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd"
>
<bean id="doSomething" class="com.xyd.demo1.DoSomething">
<constructor-arg ref="person"/> <!-- 注入American -->
</bean> <bean id="person" class="com.xyd.demo1.American"><!-- American类 -->
</bean>
</beans>
以上xml声明了2个bean,一个DoSomething类,同时构造参数传入了American bean的引用。一个American类。
下面修改测试代码
public static void main(String[] args) {
//DoSomething doSomething=new DoSomething(new American());
//doSomething.doing();
ClassPathXmlApplicationContext context=new ClassPathXmlApplicationContext("SayHello.xml");
DoSomething doSomething=context.getBean(DoSomething.class);
doSomething.doing();
}
使用XML应用上下文装载配置文件,然后使用getBean获得DoSomething类的实例,然后直接调用其doing()方法,输出American say hello!
四月 07, 2018 10:48:13 下午 org.springframework.context.support.ClassPathXmlApplicationContext prepareRefresh
信息: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@506c589e: startup date [Sat Apr 07 22:48:13 CST 2018]; root of context hierarchy
四月 07, 2018 10:48:13 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
信息: Loading XML bean definitions from class path resource [SayHello.xml]
American say hello!
XML应用上下文获得了bean配置文件,得到DoSomething的引用后只需要简单的调用doing()就可以了,这个类完全不知道传入的是哪个Person接口的实例,只有配置文件中知道哪个实例被传入。
应用切面(AOP)
DI能然相互协作的软件保持松耦合,面向切面(AOP)允许把遍布应用各处的功能 分离出来形成可重用的组件。如需要在调用sayHello记录一下日志等等,通常称为横切关注点,借助AOP可以使这些服务模块化。
还是以上述例子,但是要增加一个功能,比如美国人说hello之前进行询问,之后给一个回应。
public class Reply {
public void sayHelloBefor(){ //sayHello前调用
System.out.println("say hello please!");
}
public void sayHelloAfter(){ //sayHello之后调用
System.out.println("really good");
}
}
传统的的做法是下面这样
public class DoSomething {
Person person;
Reply reply=new Reply();
public DoSomething(Person person){
this.person=person;
}
public void doing(){
reply.sayHelloBefor(); //DoSomething应该管理它吗?
person.sayHello();
reply.sayHelloAfter();
}
}
程序正常输出了
say hello please!
American say hello!
really good
但是这简单的代码变的复杂,如果还需要没有人进行回应的场景那会变得更复杂,而利用AOP可以声明在sayHello前必须进行请求和询问,而DoSomething本身不需要访问Reply的代码,下面修改配置文件。
<?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:tx="http://www.springframework.org/schema/tx"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd"
>
<bean id="doSomething" class="com.xyd.demo1.DoSomething">
<constructor-arg ref="person"/> <!-- 注入American -->
</bean> <bean id="person" class="com.xyd.demo1.American"> <!-- American类 -->
</bean> <bean id="reply" class="com.xyd.demo1.Reply"> <!-- Reply类 -->
</bean> <aop:config>
<aop:aspect ref="reply"> <!-- 引用reply bean -->
<aop:pointcut id="sayHello" expression="execution(* *.doing(..))" /> <!-- 定义切点( AspectJ切点表达式 )--> <aop:before method="sayHelloBefor" pointcut-ref="sayHello"/> <!-- 声明前置通知 --> <aop:after method="sayHelloAfter" pointcut-ref="sayHello"/> <!-- 声明后置通知 -->
</aop:aspect>
</aop:config>
</beans>
接下来运行一下程序,输出如下结果。
say hello please!
American say hello!
really good
AOP所做的事情,就是通过少量的配置,就可以吧Reply声明为一个切面,Reply仍然是一个POJO,不需要改变现有代码。
Bean容器
在Spring的应用中,应用对象生存于Spring容器中,容器负责创建、装配它们,配置并且管理对象的整个声明周期。容器是Spring框架的核心,使用DI管理构成应用的组件,会创建相互协作的组件之间的关联。
Spring中容器并不只有一个,其自带了多个容器实现,可归类为两种不同类型:
● bean工厂(由org.springframework.beans.factory.eanFactory接口定义,最简单,提供基本的DI支持)
● 应用上下文(由org.springframework.context.applicationContext接口定义,基于BeanFactory构建,提供应用框架级别的服务,例如从属性解析文本以及发布应用实践给感兴趣的事件监听者)
常用的容器类型为应用上下文,经常遇到的应用上下文:
● AnnotationConfigApplicationContext:从一个或多个基于Java的配置类中加载Spring上下文;
● AnnotationConfigApplicationContextAnnotationConfigWebApplicationContext:从一个或多个基于Java的配置类中加载Spring Web的应用上下文
● ClassPathXmlApplicationContext:从类路径下的一个或多个XML配置文件中加载上下文定义,把应用上下文的定义文件作为类资源。
● FileSystemXmlapplictioncontext:从文件系统下的一个或多个XML配置文件中加载上下文定义。
● XMLWebApplicationContext:从Web应用下的一个或多个XMl配置文件中加载上下文定义。
无论使用何种类型的应用上下文,将bean加载到bean工厂的过程都是相似的。
下面的代码加载一个xml配置文件的应用上下文:
ClassPathXmlApplicationContext context=new ClassPathXmlApplicationContext("SayHello.xml");
获得应用上下文之后,就可以调用上下文的getBean()方法获得bean。
bean的生命周期
1、对bean进行实例化,new;
2、将值和bean的引用注入到bean对应的属性中 ;
3、如果bean实现了BeanNameAware接口,则将bean的ID传递给setBean-Name()方法;
4、如果bean实现了BeanFactoryAware接口,则调用setBeanFactory()方法,将BeanFactory容器实例传入;
5、如果bean实现了ApplicationContextAware接口,则将调用setApplicationContext()方法,将bean所在的应用上下文的引用传进来;
6、如果bean实现了BeanPostProcessor接口,则将调用它们的post-ProcessBeforeInitialization()方法;
7、如果bean实现了InitializeingBean接口,则将调用它们的after-PropertiesSet()方法,类似如果bean使用init-method声明了初始化方法,此方法也会调用。
8、如果bean实现了BeanPostProcessor,则将调用它们的post-ProcessAfterInitialization()方法;
9、此时bean已经准备就绪,可以被应用使用,它们将一直驻留在应用上下文中,直到上下文被销毁;
10、如果bean实现了DisposableBean接口,将调用它的destroy()接口方法,同样,如果bean使用destroy-method声明了销毁方法,该方法也会被调用;
Spring学习笔记-Spring之旅-01的更多相关文章
- Spring学习笔记--spring+mybatis集成
前言: 技术的发展, 真的是日新月异. 作为javaer, 都不约而同地抛弃裸写jdbc代码, 而用各种持久化框架. 从hibernate, Spring的JDBCTemplate, 到ibatis, ...
- Spring学习笔记—Spring之旅
1.Spring简介 Spring是一个开源框架,最早由Rod Johnson创建,并在<Expert One-on-One:J2EE Design and Development> ...
- Spring学习笔记--Spring IOC
沿着我们上一篇的学习笔记,我们继续通过代码学习IOC这一设计思想. 6.Hello类 第一步:首先创建一个类Hello package cn.sxt.bean; public class Hello ...
- Spring学习笔记--Spring配置文件和依赖注入
Spring配置文件 1.alias:设置别名,为bean设置别名,并且可以设置多个别名; <!-- 设置别名 --> <alias name="user" al ...
- Spring学习笔记——Spring中的BeanFactory与FactoryBean
BeanFactory BeanFactory是Spring的org.springframework.beans.factory下的一个接口,是Spring IOC所遵守的基本编程规范.他的实现类有D ...
- Spring学习笔记--Spring简介
1.spring:给软件行业带来了春天; 2.spring的理念:spring框架的初衷是使的现有的更加实用,spring不是创造轮子(技术或框架),而是使现有的轮子更好的运转;spring本身是一个 ...
- Spring学习笔记——Spring依赖注入原理分析
我们知道Spring的依赖注入有四种方式,各自是get/set方法注入.构造器注入.静态工厂方法注入.实例工厂方法注入 以下我们先分析下这几种注入方式 1.get/set方法注入 public cla ...
- Spring学习笔记--Spring表达式语言SpEL
Spring3引入了Spring表达式语言(Spring Expression Language,SpEL).SpEL是一种强大的.简洁的装配Bean的方式,它通过运行期执行的表达式将值装配到Bean ...
- 转:Spring学习笔记---Spring Security登录页
转:http://axuebin.com/blog/2016/06/21/spring-security/?utm_source=tuicool&utm_medium=referral. 提示 ...
随机推荐
- matplotlib如何显示中文
问题:matplotlib不能渲染中文 想设定为中文字体,网上搜索的方法几乎都是下面这样,已经把字体拷贝到了程序目录下了,然而并没有生效 plt.rcParams [ font.sans-serif' ...
- oracle数据库的启动、关闭、连接
登陆数据库 方法一: $ sqlplus / as sysdba [oracle@dev /]$ sqlplus / as sysdba SQL*Plus: Release Production on ...
- Emmet:HTML/CSS代码快速编写
html缩写: 1. 初始化 HTML文档需要包含一些固定的标签,比如<html>.<head>.<body>等,现在你只需要1秒钟就可以输入这些标签.比如输入“ ...
- MySQL常用关键词
MySQL常用关键词 1. 显示表departments的结构:DESC DESC departments; 2. 显示出表employees中的全部job_id(不能重复):DISTINCT SE ...
- JMeter接口测试-循环读取库的用户信息
前言 如何实现循环读取数据库的用户信息,并传递到下一个登录请求呢,下面我们一起来学习吧!在之前我们已经学会了利用JMeter连接数据库了,具体操作可以看我之前的随笔JMeter接口测试-JDBC测试 ...
- float布局打破标准流,神助攻clear清浮动
布局是什么?根据功能划分小块,再根据设计稿还原,书写静态页面,然后再在块里面填充内容,完善功能,js施加交互效果.div作为一个容器,独占一行,代码书写习惯从上至下属于标准流,而浮动float的css ...
- C# Excel导出超出65536行报错 Invalid row number (65536) outside allowable range (0..65535)
C# Excel导出超出65536行报错 Invalid row number (65536) outside allowable range (0..65535) 一:报错 Invalid row ...
- 50元求解pyqt加载并显示pdf问题
50块钱求解决pyqt5加载pdf文档并显示,类似briss软件的效果
- 全网小说免费阅读下载APP
先说主题:今天分享一个全网小说免费阅读下载APP.这篇文章是凌晨2点钟写的,原因呢可能有两点: 半夜无眠,一时兴起就想分享点有用的东西给大家,就问你感动不?其实吧,可能是晚上喝了点儿浓茶导致的无眠,所 ...
- Linux 文件(持续更新)
一.文件类型 Linux操作系统把所有内容(文件.图片.视频.设备)都当作文件看待.处理,即一切皆文件. Linux系统把所有文件分为七种类型: 文件类型 文件类型标识 说明 使用ls -l命令查看文 ...