aop概念理解(8)

2019-08-29 00:30

强制使用CGLIB代理需要将 的 proxy-target-class 属性设为true:

...

请注意这个属性的设置仅对 每一个 有效; 你可能有多个 ,其中有的强制使用CGLIB代理,有的没有。

当需要使用CGLIB代理和@AspectJ自动代理支持,请按照如下的方式设置 的 proxy-target-class 属性:

除了在配置文件中使用 或者 来声明切面。 同样可以通过编程方式来创建代理通知(advise)目标对象。关于Spring AOP API的详细介绍,请参看下一章。这里我们重点介绍自动创建代理。

类 org.springframework.aop.aspectj.annotation.AspectJProxyFactory 可以为@AspectJ切面的目标对象创建一个代理。该类的基本用法非常简单,示例如下。请参看Javadoc获取更详细的信息。

// create a factory that can generate a proxy for the given target object AspectJProxyFactory factory = new AspectJProxyFactory(targetObject);

// add an aspect, the class must be an @AspectJ aspect

// you can call this as many times as you need with different aspects factory.addAspect(SecurityManager.class);

// you can also add existing aspect instances, the type of the object // supplied must be an @AspectJ aspect factory.addAspect(usageTracker);

// now get the proxy object...

MyInterfaceType proxy = factory.getProxy();6.7. 在Spring应用中使用AspectJ

到目前为止本章讨论的一直是纯Spring AOP。 在这一节里面我们将介绍如何使用AspectJ compiler/weaver来代替Spring AOP或者作为它的补充,因为有些时候Spring AOP单独提供的功能也许并不能满足你的需要。

Spring提供了一个小巧的AspectJ aspect library (你可以在程序发行版本中单独使用 spring-aspects.jar 文件,并将其加入到classpath下以使用其中的切面)。 Section 6.7.1, “在Spring中使用AspectJ来为domain object

进行依赖注入” 和 Section 6.7.2, “Spring中其他的AspectJ切面” 讨论了该库和如何使用该库。 Section 6.7.3, “使用Spring IoC来配置AspectJ的切面” 讨论了如何对通过AspectJ compiler织入的AspectJ切面进行依赖注入。 最后Section 6.7.4, “在Spring应用中使用AspectJ Load-time weaving(LTW)”介绍了使用AspectJ的Spring应用程序如何装载期织入(load-time weaving)。

6.7.1. 在Spring中使用AspectJ来为domain object进行依赖注入

Spring容器对application context中定义的bean进行实例化和配置。 同样也可以通过bean factory来为一个已经存在且已经定义为spring bean的对象应用所包含的配置信息。 spring-aspects.jar中包含了一个

annotation-driven的切面,提供了能为任何对象进行依赖注入的能力。 这样的支持旨在为 脱离容器管理 创建的对象进行依赖注入。 Domain object经常处于这样的情形:它们可能是通过 new 操作符创建的对象, 也可能是ORM工具查询数据库的返回结果对象。

包 org.springframework.orm.hibernate.support 中的类

DependencyInjectionInterceptorFactoryBean 可以让Spring为Hibernate创建并且配置prototype类型的domain object(使用自动装配或者确切命名的bean原型定义)。 当然,拦截器不支持配置你编程方式创建的对象而非检索数据库返回的对象。 其他framework也会提供类似的技术。仍是那句话,Be Pragramatic选择能满足你需求的方法中最简单的那个。 请注意前面提及的类 没有 随Spring发行包一起发布。 如果你希望使用该类,需要从Spring CVS Respository上下载并且自行编译。 你可以在Spring CVS respository下的 'sandbox' 目录下找到该文件。

@Configurable 注解标记了一个类可以通过Spring-driven方式来配置。 在最简单的情况下,我们只把它当作标记注解:

package com.xyz.myapp.domain;

import org.springframework.beans.factory.annotation;

@Configurable

public class Account { ...

当只是简单地作为一个标记接口来使用的时候,Spring将采用和该已注解的类型(比如Account类)全名 (com.xyz.myapp.domain.Account)一致的bean原型定义来配置一个新实例。 由于一个bean默认的名字就是它的全名,所以一个比较方便的办法就是省略定义中的id属性:

如果你希望明确的指定bean原型定义的名字,你可以在注解中直接定义:

package com.xyz.myapp.domain;

import org.springframework.beans.factory.annotation;

@Configurable(\public class Account { ...

Spring会查找名字为\的bean定义,并使用它作为原型定义来配置一个新的Account对象。

你也可以使用自动装配来避免手工指定原型定义的名字。 只要设置

@Configurable 注解中的autowire属性就可以让Spring来自动装配了: @Configurable(autowire=Autowire.BY_TYPE) 或者

@Configurable(autowire=Autowire.BY_NAME,这样就可以按类型或者按名字自动装配了。

最后,你可以设置 dependencyCheck 属性,通过设置,Spring对新创建和配置的对象的对象引用进行校验 (例如:

@Configurable(autowire=Autowire.BY_NAME,dependencyCheck=true) )。 如果这个属性被设为true,Spring会在配置结束后校验除了primitives和collections类型的所有的属性是否都被赋值了。

仅仅使用注解并没有做任何事情。但当注解存在时,spring-aspects.jar中的 AnnotationBeanConfigurerAspect 就起作用了。 实质上切面做了这些:当初始化一个有 @Configurable 注解的新对象时,Spring按照注解中的属性来配置这个新创建的对象。 要实现上述的操作,已注解的类型必须由AspectJ weaver来织入 - 你可以使用一个 build-time ant/maven任务来完成 (参见AspectJ Development Environment Guide) 或者使用load-time weaving(参见 Section 6.7.4, “在Spring应用中使用AspectJ Load-time weaving(LTW)”)。

类 AnnotationBeanConfigurerAspect 本身也需要Spring来配置(获得bean factory的引用,使用bean factory配置新的对象)。 为此Spring AOP命名空间定义了一个非常方便的标签。如下所示,可以很简单的在application context配置文件包含这个标签中。

如果你使用DTD代替Schema,对应的定义如下:

class=\gurerAspect\

factory-method=\在切面配置完成 之前 创建的@Configurable对象实例会导致在log中留下一个warning,并且任何对于该对象的配置都不会生效。 举一个例子,一个Spring管理配置的bean在被Spring初始化的时候创建了一个domain object。 对于这样的情况,你需要定义bean属性中的\属性来手动指定该bean依赖于configuration切面。

class=\

depends-on=\ConfigurerAspect\ ...

6.7.1.1. @Configurable object的单元测试

提供 @Configurable 支持的一个目的就是使得domain object的单元测试可以独立进行,不需要通过硬编码查找各种倚赖关系。 如果 @Configurable 类型没有通过AspectJ织入, 则在单元测试过程中注解不会起到任何作用,测试中你可以简单的为对象的mock或者stub属性赋值,并且和正常情况一样的去使用该对象。 如果 @Configurable 类型通过AspectJ织入, 我们依然可以脱离容器进行单元测试,不过每次创建一个新的 @Configurable 对象时都会看到一个warning标示该对象不受Spring管理配置。

6.7.1.2. 多application context情况下的处理

AnnotationBeanConfigurerAspect 通过一个AspectJ singleton切面来实现对 @Configurable 的支持。 一个singleton切面的作用域和一个静态变量的作用域是一样的,例如,对于每一个classloader有一个切面来定义类型。 这就意味着如果你在一个classloader层次结构中定义了多个application context的时候就需要考虑在哪里定义 bean和在哪个classpath下放置Srping-aspects.jar。

考虑一下典型的Spring web项目,一般都是由一个父application context定义大部分business service和所需要的其他资源,然后每一个servlet拥有一个子application context定义。 所有这些context共存于同一个classloader hierarchy下,因此对于全体context,AnnotationBeanConfigurerAspect 仅可以维护一个引用。 在这样的情况下,我们推荐在父application context中定义 bean: 这里所定义的service可能是你希望注入domain object的。 这样做的结果是你不能为子application context中使用@Configurable的domain object配置bean引用(可能你也根本就不希望那么做!)。

当在一个容器中部署多个web-app的时候,请确保每一个web-application使用自己的classloader来加载spring-aspects.jar中的类(例如将

spring-aspects.jar放在WEB-INF/lib目录下)。 如果spring-aspects.jar被放在了容器的classpath下(因此也被父classloader加载),则所有的web application将共享一个aspect实例,这可能并不是你所想要的。

6.7.2. Spring中其他的AspectJ切面 除了 @Configurable 支持,spring-aspects.jar包含了一个AspectJ切面可以用来为那些使用了 @Transactional annotation 的类型和方法驱动Spring事务管理(参见 Chapter 9, 事务管理)。 提供这个的主要目的是有些用户希望脱离Spring容器使用Spring的事务管理。

对于AspectJ程序员,希望使用Spring管理配置和事务管理支持,不过他们不想(或者不能)使用注解,spring-aspects.jar也包含了一些抽象切面供你继承来提供你自己的切入点定义。 参见 AbstractBeanConfigurerAspect 和 AbstractTransactionAspect 的Javadoc获取更多信息。 作为一个例子,下面的代码片断展示了如何编写一个切面,然后通过bean原型定义中和类全名匹配的来配置domian object中所有的实例:

public aspect DomainObjectConfiguration extends AbstractBeanConfigurerAspect {

public DomainObjectConfiguration() {

setBeanWiringInfoResolver(new ClassNameBeanWiringInfoResolver()); }

/**

* The creation of a new bean (any object in the domain model) */

protected pointcut beanCreation(Object beanInstance) : initialization(new(..)) &&

SystemArchitecture.inDomainModel() && this(beanInstance);

}6.7.3. 使用Spring IoC来配置AspectJ的切面

当在Spring application中使用AspectJ的时候,很自然的会想到用Spring来管理这些切面。 AspectJ runtime自身负责切面的创建,这意味着通过Spring来管理AspectJ 创建切面依赖于切面所使用的AspectJ instantiation model(per-clause)。

大多数AspectJ切面都是 singleton 切面。 管理这些切面非常容易,和通常一样创建一个bean定义引用该切面类型就可以了,并且在bean定义中包含 factory-method=\这个属性。 这确保Spring从AspectJ获取切面实例而不是尝试自己去创建该实例。示例如下:


aop概念理解(8).doc 将本文的Word文档下载到电脑 下载失败或者文档不完整,请联系客服人员解决!

下一篇:java练习题+答案

相关阅读
本类排行
× 注册会员免费下载(下载后可以自由复制和排版)

马上注册会员

注:下载文档有可能“只有目录或者内容不全”等情况,请下载之前注意辨别,如果您已付费且无法下载或内容有问题,请联系我们协助你处理。
微信: QQ: