完整代码请见:https://github.com/codercuixi...
为了降低Java开发的复杂性,Spring采用了以下4种策略:
- 基于pojo的轻量级和最小侵入式编程
- 通过依赖注入和面向接口实现松耦合
- 基于切面和惯例进行声明式编程
- 通过切面和模板减少样本式代码
一. 依赖注入
(利用面向接口编程的思想,由Spring应用上下文负责依赖注入)
通过依赖注入(DI ,Dependency Inject),对象的依赖关系由系统中负责协调各对象的第三方组件在创建对象的时候进行设定。对象无需自行创建或管理他们的依赖关系,如图1.1所示,依赖关系被自动注入到需要他们的对象中去。
Spring通过应用上下文(Application Context)来装在bean定义并把组装起来。Spring自带了很多很多应用上下文,他们之间的区别仅仅在于如何加载配置。
两种方式来表示Spring的应用上下文。
1.注解(墙裂推荐使用)
- 1通过@Configuration来声明这个类是Java Bean的配置类,通过在具体的方法前面添加@Bean注解来声明一个Bean
package sia.knights;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.io.PrintStream;
/**
* Create by cuixin on 2018/8/25
**/
@Configuration public class KnightConfig {
@Bean
public Knight knight() {
return new BraveKnight(quest());
}
@Bean
public Quest quest() {
return new SlayDragonQuest(stream());
}
@Bean
public PrintStream stream() {
return new FakePrintStream();
}
}
1.2. 通过@ContextConfiguration来配置Spring应用上文下信息
package sia.knights;
import org.junit.After;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.support.AnnotationConfigContextLoader;
import javax.annotation.Resource;
/**
* Create by cuixin on 2018/8/25
**/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = KnightConfig.class, loader = AnnotationConfigContextLoader.class)
public class KnightJavaConfigInjectionTest {
@Autowired
private Knight knight;
@Resource
private FakePrintStream printStream;
@After
public void clearPrintStream() {
printStream.clear();
}
@Test
public void shuoldInjectKnightWithSlayDragonQuest() {
knight.embarkOnQuest();
assert "Embarking on quest to slay the dragon!\n".equals(printStream.getPrintedString());
}
}
2.xml配置文件(基本已经弃用)
2.1. knigh.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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="knight" class="sia.knights.BraveKnight">
<constructor-arg ref="quest"/>
</bean>
<bean id="quest" class="sia.knights.SlayDragonQuest">
<constructor-arg value="#{T(System).out}"/>
</bean>
</beans>
2.2 通过Spring提供的ClassPathXmlApplicationContext或者FileSystemXmlApplicationContext来寻找xml配置文件
package sia.knights;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* Create by cuixin on 2018/8/24
**/
public class KnightMain {
public static void main(String args[]){
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring/knight.xml");
Knight knight = context.getBean(Knight.class);
knight.embarkOnQuest();
context.close();
}
}
二.面向切面编程 AOP
面向切面编程(aspect-oriented programming,AOP)允许你把遍布应用各处的功能分离出来形成可重用的组件。
系统由多个组件组成,比如核心业务,日志,事务管理和安全。
日志,事务管理和安全这样的系统服务经常融入到具有核心业务逻辑的组件中去,这些系统服务通过被称为横切关注点。
如果不管不问,那么这些横切关注点会重复出现在多个组件中,也会增加每一个组件的复杂性。
AOP能够使这些服务模块化,并且以声明的方式将他们需要影响的组件中去。我们可以将切面想象成为覆盖在很多组件之上的一个外壳。
2.1. 利用xml配置aop
<?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"
xsi:schemaLocation="http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="knight" class="sia.knights.BraveKnight">
<constructor-arg ref="quest" />
</bean>
<bean id="quest" class="sia.knights.SlayDragonQuest">
<constructor-arg value="#{T(System).out}" />
</bean>
<bean id="minstrel" class="sia.knights.Minstrel">
<constructor-arg value="#{T(System).out}" />
</bean>
<aop:config>
<aop:aspect ref="minstrel">
<aop:pointcut id="embark" expression="execution(* *.embarkOnQuest(..))"/>
<aop:before pointcut-ref="embark" method="singBeforeQuest"/>
<aop:after pointcut-ref="embark" method="singAfterQuest"/>
</aop:aspect>
</aop:config>
</beans>
三. 使用模板消除样本式代码
样板代码:为了实现通用的和简单的任务,不得不一遍遍重复写的代码。
3.1 容纳你的Bean
在基于Spring的应用中,你的应用对象存在于Spring容器(container)中,如图1.4所示,Sring容器负责创建帝乡,装配他们,配置他们并管理他们的整个生命周期,从生存到死亡(在这里,可能就是new到finalize)。
容器是Spring的核心。Spring容器使用DI管理构成应用的组件,他会创建相互协作的组件之间的关联。
3.2 Spring容器的两种实现类型实现
3.2.1. bean工厂不常用。
由org.springframework.benas.factory.BeanFactory接口定义,是简单的容器,提供最简单的DI支持。应用上下文由orgspringframework.context.ApplicationContext接口定义)基于BeanFactory构建,并提供应用框架级别的
3.2.2.使用应用上下文
AnnotationConfigApplicationContext: 从一个或多个基于Java的配置类中加载Spring应用上下文
ApplicationContext context = new AnnotationConfigApplicationContext(KnightConfig.class)
AnnotationConfigWebApplicationContext:从一个或多个基于Java的配置类中加载Spring Web应用上下文
ClassPathXmlApplicationContext:从类路径下的一个或多个xml配置文件中加载上下文定义,把应用上下文的定义文件作为类资源
ApplicationContext context = new ClassPathXmlApplicationContext("knight.xml")
FileSystemXmlApplicationContext:从文件系统的一个或多个xml配置文件中加载上下文定义
ApplicationContext context = new FileSystemXmlApplicationContext("c://knight.xml")
XmlWebApplicationContext:从Web应用的一个或多个xml配置文件中加载上下文定义。
3.3 bean的生命周期
四.俯瞰Spring的风景线
4.1 Spring模块
4.2 Spring portfolio
srping-web-flow . Spring web Service, Spring security,Spring Integration, SpringBatch, Spring Data, Spring Social,
Spring Mobile, Spring Boot
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。