Spring(一) 概述
- 基于POJO的轻量级和最小侵入性编程
- 通过依赖注入和面向接口实现松耦合
- 基于切面和惯例进行声明式变成
- 通过切面和模版减少样板式代码
Spinrg不会强迫实现Spring规范的接口或继承Spring规范的类,不会应为使用Spring将自己写的代码弄乱,最坏的情况就是使用了Spring的注解。
依赖注入(IOC/DI)
任何一个项目都会由两个或者更多的类组成,这些类相互之间进行协作来完成特定的业务逻辑。按照传统的做法每个对象负责管理与自己项目写作的对象(即他所依赖的对象 this.a = new A() )的引用,这将会导致高度耦合和难以测试的代码)
public class A{
private B b;
public A(){
this.b=new B(); <----- 与B类紧密耦合
}
}
耦合具有两面性
一方面紧密耦合的代码难以测试、、难以复用、难以理解、并且典型地表现出“打地鼠”式的bug特性(修复一个bug,将会出现一个或者更多的新bug)
另一方面一定成都的耦合是必须的—-完全没有耦合的代码什么也做不了。为了完成有实际意义的功能,不同的类必须以适当的方式进行交互。
耦合是必须的,但是应当被小心谨慎的去管理
构造注入
public class C{
private D d; //接口
public C(D d){
this.d; <--------构造器注入
}
}
上面代码中的C没有与特定的D接口发生耦合,只需要C实现了D接口,那么具体那种类型的D就无所谓了,这就是DI带来的最大收益—-松耦合。如果之通过接口来表明依赖关系,那么这种依赖就能够在对象本身毫不知情的情况下,用不同的具体实现进行替换
<bean id="c" class="com.leco.C">
<constructor-arg ref="d"/>
</bean>
<bean id="d" class="com.leco.D">
</bean>
以上是构造注入的配置文件
因为配置文件中是使用的XML进行配置,所以选择ClassPathXmlApplicationContext作为应用上下文,这个类用于加载类路径下一个或者多个XML的配置文件
public static void main (String []args){
ClassPathXmlApplicationContext context =
new ClassPathXmlApplicationContext
("/WEB-INF/spring-config.xml");
C c = context.getBean(C.class);
System.out.print(c.getClass().getName());
}
context.clone();
面向切面(AOP)
DI能让相互协作的组件保持松散耦合,而面向切面变成允许你把遍布应用各处的功能分离出来形成可重用的组建
面向切面变成往往被定义为促使软件系统实现关注点的分离技术,系统由许多不同的组建组成,每一个组建个负责一块特定的功能,除了实现自身核心功能外,还需要实现额外的任务(如:日志、事务管理、安全检查等)融入到自身具有核心业务逻辑的组建中,这些系统服务通常被称为横切关注点,应为他们会跨越系统的多个组建。
AOP能使这些服务模块化,并以声明的方式将他们应用到他们需要影响的组建中去,所造成的结果就是这些组建会具有更高的内聚性并且更加关注自己的业务,不需要了解设计系统服务带来的复杂,总之AOP能确保POJO的简单性。
public vlass C{
private A a;
private B b;
C(A a,B b){
this.a=a;
this.b=b;
}
public void toAll(){
b.toB1();
a.toA();
b.toB2(); <--------必须调用B的toB()方法
}
}
以上的代码A类所调用的方法是C类中所要作的核心事情,B类所调用的方法并不是,所以就可以通过AOP将B抽取为一个切面,在Spring配置文件中声明它。
<bean id="c" class="com.leco.C">
<constructor-arg ref="A"/>
</bean>
<bean id="a" class="com.leco.A">
</bean>
<bean id="b" class="com.leco.B">
</bean>
<aop:config>-----------------------------AOP声明
<aop:aspect ref="b">--------------------------------切面
<aop:pointcut id="bembark"-----------------------------切入点
expression="execution(* *.toA(..))" />
<aop:before pointcut-ref="bembark"--------------------前置通知
method="singBeforeQuest"/>
<aop:after pointcut-ref="bembark"---------------------后置通知
method="singAfterQuest"/>
</aop:aspect>
</aop:config>