Spring探究——Bean和AOP

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)换成@


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值