Spring提倡面向接口编程,面向接口与依赖注入协作实现了松散耦合。接口可以使类的引用不需要任何改变就可以支持一个接口的新实现,保持了弱耦合。
当spring容器加载Bean时,会使用默认构造器实例化Bean。
new com.springinaction.类名();
XML装配
Spring的多种XML命名空间:
①通过构造器注入创建Bean(结合XML声明Bean,并赋值到对应属性):
<bean id="poeticDuke"
class="com.springinaction.springidol.PoeticJuggler">
<constructor-arg value="15" />
<constructor-arg ref="sonnet" /><!--ref标识应该装配一个引用而不是字面值-->
</bean>
<bean id="sonnet"
class="com.springinaction.springidol.Sonnet" />
②通过工厂方法创建Bean.
public class Stage {
private Stage() {}
private static class StageSingletonHolder {
static Stage instance = new Stage();
}
public static Stage getInstance() {
return StageSingletonHolder.instance;
}
}
<bean id="stage" class="com.springinaction.springidol.Stage" factory-method="getInstance"></bean>
所有Spring Bean默认都是单例。其中scope声明了作用域,如图:
Spring的装配通过setter方式注入。而javabean的属性一般是私有的,且有一组存取器,所以JavaBean可以与XML配合。有时候我们会听到内部bean,即类内部的类,是定义在其他Bean内部的Bean。内部bean没有ID属性。
我们可以看出,采用标准的XML装配Bean的属性代码比较多,能否为它减肥?使用p名称空间,命名空间p主要优点:简洁。
引入 xmlns:p="http://www.springframework.org/schema/p"
就可以使用p空间。
<bean name="john-classic" class="com.example.Person">
<property name="name" value="Nan"/>
<property name="spouse" ref="jane"/>
</bean>
<bean name="john-modern" class="com.example.Person"
p:name="Nan"
p:spouse-ref="jane"/>
当bean的属性值为复数,可用集合配置元素。
集合元素有<list> <set> <map> <props>
XML配置文件中注入值是静态的,SpEL为属性装配的值在运行期执行提供了可能。
更多关于SpEL的内容可参考:http://www.importnew.com/17692.html
自动装配
随着应用的不断发展,不得不编写越来越复杂的XML配置。自动装配和自动检测可以显著较少配置数量。
自动装配的4种类型:
byName、byType、constructor、autodetect
基于注解的自动装配:<context:annotation-config />
配置完,才可添加注解。
@Autowired Spring自带
@Inject JSR-330
@Resource JSR-250
@Autowired可在setter方法使用、标注构造器、传入引用的方法、甚至直接标注属性(即使是私有变量且删除掉setter方法)。
但是当装配失败的时候会抛出异常,可以通过可选配置,让装配失败时,置值为null而不抛异常。
@Autowire(required=false)
private Instrument instrument;
限定歧义性依赖:@Qualifier
假如Instrument接口有两种乐器的实现guitar、pinao,这时@Autowire会不知道装配哪一个,使用@Qualifier可以指定某个实现。
@Autowire
@Qualifier("guitar")
private Instrument instrument;
@Inject和@Autowire一样,但@Inject没有required属性,所以依赖关系必须存在。
@Inject
@Named("guitar")
private Instrument instrument;
@Value不仅可以装配静态值,它可以在注解注入中使用表达式。通过SpEL表达式可以动态取值,如@Value(“#systemProperties.key”)。
自动装配让解耦提升到一个新高度。
<context:annotation-config />
仍然需要使用<bean>
显示定义Bean,<context:component-scan>
可以代替它,使其不使用<bean>
元素。
<context:component-scan base-package="com.sibat.test.bean">
</context:component-scan>
package,扫描指定的包及其所有子包.
过滤器:
spring有五种过滤器类型:annotation、assignable、aspectj、custom、 regex.
//哪些bean需要实例化
<context:exclude-filter type="annotation" expression="...">
//哪些bean不需要实例化
<context:include-filter type="assignable" expression="...">
面向切面
在软件中,有些行为对大多数应用而言都是通用的。日志、安全和事务管理,分布于应用多处的功能被称为横切关注点。
AOP所要解决的是横切关注点和业务逻辑分离。
实现重用的常见方式是:继承与委托。前者使对象的表现变脆弱,后者可能进行复杂调用。切面就提供了另外一种良好的选择。
术语:通知(切面的功能)、切点(缩小切面范围)、连接点(在应用执行过程中能够插入切面的一个点)。
下图可以很好的描述AOP的概念:
spring切面的5种通知类型:
Before(方法被调用前通知)、After(方法被调用后通知)、After-returning(方法执行成功后通知)、After-throwing(方法抛出异常后通知)、Around(环绕通知)
可参看:http://11189738.blog.51cto.com/11179738/1743383
<bean id="audience"
class="com.springinaction.springidol.AroundAudience" />
<!--非环绕通知案例-->
<aop:config>
<aop:aspect ref="audience">
<aop:pointcut id="performance" expression=
"execution(* com.springinaction.springidol.Performer.perform(..))"
/>
<aop:before
pointcut-ref="performance"
method="takeSeats" />
<aop:before
pointcut-ref="performance"
method="turnOffCellPhones" />
<aop:after-returning
pointcut-ref="performance"
method="applaud" />
<aop:after-throwing
pointcut-ref="performance"
method="demandRefund" />
</aop:aspect>
</aop:config>
<!--环绕通知案例-->
<aop:config>
<aop:aspect ref="audience">
<aop:pointcut id="performance" expression=
"execution(* com.springinaction.springidol.Performer.perform(..))"
/>
<aop:around
pointcut-ref="performance"
method="watchPerformance" />
</aop:aspect>
</aop:config>
切面Aspect:通知和切点的结合。定义了内容,在何时何处完成功能。
引入Introduction:向现有类添加新方法或属性。
织入Weaving:切面在指定的连接点被织入到目标对象中。
创建切点来定义切面织入的连接点是AOP的基本功能。
当拦截到方法调用时,在调用目标Bean前,代理会执行切面逻辑。Spring AOP只支持方法连接点,如果需要方法拦截外的连接点拦截需要利用Aspect来协助了。
切点和通知是切面最基本元素。 Spring是基于代理的,而某些切点表达式与基于代理的AOP无关。
java不是动态语言,一旦类编译完成就很难再为它添加新功能了。实际上AOP可以添加新功能(aop:declare-parents)。
可参看:http://www.cnblogs.com/xing901022/p/4265748.html
Spring AOP的功能比较弱,AspectJ切面可以作为补充。AspectJ并不依赖于spring,没有它照样可以使用,这一点得明确。
Spring Aop实例之AspectJ注解配置
参考:《Spring实战(第3版)》
http://www.importnew.com/17692.html
http://11189738.blog.51cto.com/11179738/1743383
http://www.cnblogs.com/xing901022/p/4265748.html
作者: @nanphonfy
Email: nanphonfy (Nfzone) gmail.com 请将(Nfzone)换成@