目录 搜索
前言 简介 概览 使用场景 Spring 2.0和 2.5的新特性 简介 控制反转(IoC)容器 新的bean作用域 更简单的XML配置 可扩展的XML编写 Annotation(注解)驱动配置 在classpath中自动搜索组件 面向切面编程(AOP) 更加简单的AOP XML配置 对@AspectJ 切面的支持 对bean命名pointcut( bean name pointcut element)的支持 对AspectJ装载时织入(AspectJ load-time weaving)的支持 中间层 在XML里更为简单的声明性事务配置 对Websphere 事务管理的完整支持 JPA 异步的JMS JDBC Web层 Spring MVC合理的默认值 Portlet 框架 基于Annotation的控制器 Spring MVC的表单标签库 对Tiles 2 支持 对JSF 1.2支持 JAX-WS支持 其他 动态语言支持 增强的测试支持 JMX 支持 将Spring 应用程序上下文部署为JCA adapter 计划任务 对Java 5 (Tiger) 支持 移植到Spring 2.5 改变 支持的JDK版本 Spring 2.5的Jar打包 XML配置 Deprecated(淘汰)的类和方法 Apache OJB iBATIS Hibernate JDO UrlFilenameViewController 更新的样例应用 改进的文档 核心技术 IoC(控制反转)容器 简介 基本原理 - 容器和bean 容器 配置元数据 实例化容器 XML配置元数据的结构 多种bean bean的命名 bean的别名 实例化bean 用构造器来实例化 使用静态工厂方法实例化 使用实例工厂方法实例化 使用容器 依赖 注入依赖 构造器注入 构造器参数解析 构造器参数类型匹配 构造参数索引 Setter注入 一些例子 依赖配置详解 直接变量(基本类型、Strings类型等。) idref元素 引用其它的bean(协作者) 内部bean 集合 集合的合并 强类型集合(仅适用于Java5+) Nulls XML配置文件的简写及其他 XML-based configuration metadata shortcuts 使用p名称空间配置属性 组合属性名称 使用depends-on 延迟初始化bean 自动装配(autowire)协作者 将bean排除在自动装配之外 依赖检查 方法注入 Lookup方法注入 自定义方法的替代方案 Bean的作用域 Singleton作用域 Prototype作用域 Singleton beans和prototype-bean的依赖 其他作用域 初始化web配置 Request作用域 Session作用域 global session作用域 作用域bean与依赖 选择创建代理的类型 自定义作用域 创建自定义作用域 使用自定义作用域 定制bean特性 生命周期回调 初始化回调 析构回调 缺省的初始化和析构方法 组合生命周期机制 在非web应用中优雅地关闭Spring IoC容器 了解自己 BeanFactoryAware BeanNameAware bean定义的继承 容器扩展点 用BeanPostProcessor定制bean 使用BeanPostProcessor的Hello World示例 RequiredAnnotationBeanPostProcessor示例 用BeanFactoryPostProcessor定制配置元数据 PropertyPlaceholderConfigurer示例 PropertyOverrideConfigurer示例 使用FactoryBean定制实例化逻辑 The ApplicationContext BeanFactory 还是 ApplicationContext? 利用MessageSource实现国际化 事件 底层资源的访问 ApplicationContext在WEB应用中的实例化 粘合代码和可怕的singleton 以J2EE RAR文件的形式部署Spring ApplicationContext 基于注解(Annotation-based)的配置 @Autowired 基于注解的自动连接微调 CustomAutowireConfigurer @Resource @PostConstruct 与 @PreDestroy 对受管组件的Classpath扫描 @Component和更多典型化注解 自动检测组件 使用过滤器自定义扫描 自动检测组件的命名 为自动检测的组件提供一个作用域 用注解提供限定符元数据 注册一个LoadTimeWeaver 资源 简介 Resource接口 内置 Resource 实现 UrlResource ClassPathResource FileSystemResource ServletContextResource InputStreamResource ByteArrayResource ResourceLoader接口 ResourceLoaderAware 接口 把Resource作为属性来配置 Application context 和Resource 路径 构造application context 创建 ClassPathXmlApplicationContext 实例 - 简介 Application context构造器中资源路径的通配符 Ant风格的pattern 潜在的可移植性 classpath*: 前缀 其他关于通配符的说明 FileSystemResource 说明 校验,数据绑定,BeanWrapper,与属性编辑器 简介 使用Spring的Validator接口进行校验 从错误代码到错误信息 Bean处理和BeanWrapper 设置和获取属性值以及嵌套属性 内建的PropertyEditor实现 注册用户自定义的PropertyEditor 使用PropertyEditorRegistrars 使用Spring进行面向切面编程(AOP) 简介 AOP概念 Spring AOP的功能和目标 AOP代理 @AspectJ支持 启用@AspectJ支持 声明一个切面 声明一个切入点(pointcut) 切入点指示符(PCD)的支持 组合切入点表达式 共享通用切入点定义 示例 声明通知 前置通知 后置通知(After returning advice) 异常通知(After throwing advice) 最终通知(After (finally) advice) 环绕通知 通知参数(Advice parameters) 访问当前的连接点 传递参数给通知 确定参数名 处理参数 通知顺序 引入(Introduction) 切面实例化模型 例子 基于Schema的AOP支持 声明一个切面 声明一个切入点 声明通知 前置通知 后置通知 异常通知 最终通知 环绕通知 通知参数 通知顺序 引入 切面实例化模型 Advisor 例子 AOP声明风格的选择 Spring AOP还是完全用AspectJ? Spring AOP中使用@AspectJ还是XML? 混合切面类型 代理机制 理解AOP代理 以编程方式创建@AspectJ代理 在Spring应用中使用AspectJ 在Spring中使用AspectJ进行domain object的依赖注入 @Configurable对象的单元测试 Working with multiple application contexts Spring中其他的AspectJ切面 使用Spring IoC来配置AspectJ的切面 在Spring应用中使用AspectJ加载时织入(LTW) 第一个例子 切面 'META-INF/aop.xml' 相关类库(JARS) Spring配置 特定环境的配置 通用Java应用 Tomcat WebLogic 更多资源 Spring AOP APIs 简介 Spring中的切入点API 概念 切入点运算 AspectJ切入点表达式 便利的切入点实现 静态切入点 正则表达式切入点 属性驱动的切入点 动态切入点 控制流切入点 切入点的超类 自定义切入点 Spring的通知API 通知的生命周期 Spring里的通知类型 拦截环绕通知 前置通知 异常通知 后置通知 引入通知 Spring里的Advisor API 使用ProxyFactoryBean创建AOP代理 基础 JavaBean属性 基于JDK和CGLIB的代理 对接口进行代理 对类进行代理 使用“全局”通知器 简化代理定义 使用ProxyFactory通过编程创建AOP代理 操作被通知对象 使用“自动代理(autoproxy)”功能 自动代理bean定义 BeanNameAutoProxyCreator DefaultAdvisorAutoProxyCreator AbstractAdvisorAutoProxyCreator 使用元数据驱动的自动代理 使用TargetSource 热交换目标源 池化目标源 原型目标源 ThreadLocal目标源 定义新的Advice类型 更多资源 测试 简介 单元测试 Mock对象 JNDI Servlet API Portlet API 单元测试支持类 通用工具类 Spring MVC 集成测试 概览 使用哪个支持框架 通用目标 上下文管理及缓存 测试fixtures依赖注入 事务管理 集成测试支持类 JDBC测试支持 常用注解 JUnit 3.8遗留支持 上下文管理及缓存 测试fixture依赖注入 字段级别(Field Level)注入 事务管理 JUnit 3.8 遗留支持类 Java 5+ 专有支持 使用注解的事务相关测试 JPA支持类 Spring TestContext Framework 主要的抽象 上下文管理和缓存 测试fixture的依赖注入 事务管理 TestContext支持类 JUnit 3.8支持类 JUnit 4.4支持类 定制JUnit 4.4运行器 TestNG支持类 TestContext框架注解支持 PetClinic示例 更多资源 中间层数据访问 事务管理 简介 动机 关键抽象 使用资源同步的事务 高层次方案 低层次方案 TransactionAwareDataSourceProxy 声明式事务管理 理解Spring的声明式事务管理实现 第一个例子 回滚 为不同的bean配置不同的事务语义 <tx:advice/> 有关的设置 使用 @Transactional @Transactional 有关的设置 事务传播 required RequiresNew Nested 通知事务操作 结合AspectJ使用 @Transactional 编程式事务管理 使用TransactionTemplate 指定事务设置 使用PlatformTransactionManager 选择编程式事务管理还是声明式事务管理 与特定应用服务器集成 IBM WebSphere BEA WebLogic Oracle OC4J 常见问题的解决方法 对一个特定的 DataSource 使用了错误的事务管理器 更多的资源 DAO支持 简介 一致的异常层次 一致的DAO支持抽象类 使用JDBC进行数据访问 简介 选择一种工作模式 Spring JDBC包结构 利用JDBC核心类控制JDBC的基本操作和错误处理 JdbcTemplate类 一些示例 查询(SELECT) 更新(INSERT/UPDATE/DELETE) 其他操作 JdbcTemplate 的最佳实践 NamedParameterJdbcTemplate类 SimpleJdbcTemplate类 DataSource接口 SQLExceptionTranslator接口 执行SQL语句 执行查询 更新数据库 获取自动生成的主键 控制数据库连接 DataSourceUtils类 SmartDataSource接口 AbstractDataSource类 SingleConnectionDataSource类 DriverManagerDataSource类 TransactionAwareDataSourceProxy类 DataSourceTransactionManager类 NativeJdbcExtractor JDBC批量操作 使用JdbcTemplate进行批量操作 使用SimpleJdbcTemplate进行批量操作 通过使用SimpleJdbc类简化JDBC操作 使用SimpleJdbcInsert插入数据 使用SimpleJdbcInsert来获取自动生成的主键 指定SimpleJdbcInsert所使用的字段 使用SqlParameterSource提供参数值 使用SimpleJdbcCall调用存储过程 声明SimpleJdbcCall使用的参数 如何定义SqlParameters 使用SimpleJdbcCall调用内置函数 使用SimpleJdbcCall返回的ResultSet/REF Cursor 用Java对象来表达JDBC操作 SqlQuery类 MappingSqlQuery类 SqlUpdate类 StoredProcedure类 SqlFunction类 参数和数据处理的基本原则 为参数设置SQL类型信息 处理BLOB 和 CLOB对象 在IN语句中传入一组参数值 处理复杂类型的存储过程调用 使用ORM工具进行数据访问 简介 Hibernate 资源管理 在Spring容器中创建 SessionFactory The HibernateTemplate 不使用回调的基于Spring的DAO实现 基于Hibernate3的原生API实现DAO 编程式的事务划分 声明式的事务划分 事务管理策略 容器资源 vs 本地资源 在应用服务器中使用Hibernate的注意事项 JDO 建立PersistenceManagerFactory JdoTemplate和JdoDaoSupport 基于原生的JDO API实现DAO 事务管理 JdoDialect Oracle TopLink SessionFactory 抽象层 TopLinkTemplate and TopLinkDaoSupport 基于原生的TopLink API的DAO实现 事务管理 iBATIS SQL Maps 创建SqlMapClient 使用 SqlMapClientTemplate 和 SqlMapClientDaoSupport 基于原生的iBATIS API的DAO实现 JPA 在Spring环境中建立JPA LocalEntityManagerFactoryBean 从JNDI中获取 EntityManagerFactory LocalContainerEntityManagerFactoryBean Tomcat(5.0以上)加载时的织入配置 使用VM代理的全局加载时织入 上下文范围内的加载时织入配置 处理多持久化单元 JpaTemplate 和 JpaDaoSupport 基于原生的JPA实现DAO 异常转化 事务管理 JpaDialect The Web Web MVC framework Web框架 概述 与其他MVC实现框架的集成 Spring Web MVC框架的特点 DispatcherServlet 控制器 AbstractController 和 WebContentGenerator 其它的简单控制器 MultiActionController 命令控制器 处理器映射(handler mapping) BeanNameUrlHandlerMapping SimpleUrlHandlerMapping 拦截器(HandlerInterceptor) 视图与视图解析 视图解析器(ViewResolver) 视图解析链 重定向(Rediret)到另一个视图 RedirectView redirect:前缀 forward:前缀 本地化解析器 AcceptHeaderLocaleResolver CookieLocaleResolver SessionLocaleResolver LocaleChangeInterceptor 使用主题 简介 如何定义主题 主题解析器 Spring对分段文件上传(multipart file upload)的支持 介绍 使用MultipartResolver 在表单中处理分段文件上传 使用Spring的表单标签库 配置 form标签 input标签 checkbox标签 checkboxes标签 radiobutton标签 radiobuttons标签 password标签 select标签 option标签 options标签 textarea标签 hidden标签 errors标签 处理异常 惯例优先原则(convention over configuration) 对控制器的支持:ControllerClassNameHandlerMapping 对模型的支持:ModelMap(ModelAndView) 对视图的支持:RequestToViewNameTranslator 基于注解的控制器配置 建立dispatcher实现注解支持 使用@Controller定义一个控制器 使用@RequestMapping映射请求 使用@RequestParam绑定请求参数到方法参数 使用@ModelAttribute提供一个从模型到数据的链接 使用@SessionAttributes指定存储在会话中的属性 自定义WebDataBinder初始化 使用@InitBinder自定义数据绑定 配置一个定制的WebBindingInitializer 更多资源 集成视图技术 简介 JSP和JSTL 视图解析器 'Plain-old' JSPs versus JSTL 'Plain-old' JSP与JSTL 帮助简化开发的额外的标签 Tiles 需要的资源 如何集成Tiles UrlBasedViewResolver类 ResourceBundleViewResolver类 SimpleSpringPreparerFactory 和 SpringBeanPreparerFactory Velocity和FreeMarker 需要的资源 Context 配置 创建模板 高级配置 velocity.properties FreeMarker 绑定支持和表单处理 用于绑定的宏 简单绑定 表单输入生成宏 输入域 选择输入域 重载HTML转码行为并使你的标签符合XHTML XSLT 写在段首 Bean 定义 标准MVC控制器代码 把模型数据转化为XML 定义视图属性 文档转换 小结 文档视图(PDF/Excel) 简介 配置和安装 文档视图定义 Controller 代码 Excel视图子类 PDF视图子类 JasperReports 依赖的资源 配置 配置ViewResolver 配置View 关于报表文件 使用 JasperReportsMultiFormatView 构造ModelAndView 使用子报表 配置子报表文件 配置子报表数据源 配置Exporter的参数 集成其它Web框架 简介 通用配置 JavaServer Faces DelegatingVariableResolver FacesContextUtils Struts ContextLoaderPlugin DelegatingRequestProcessor DelegatingActionProxy ActionSupport Classes Tapestry 注入 Spring 托管的 beans 将 Spring Beans 注入到 Tapestry 页面中 组件定义文件 添加抽象访问方法 将 Spring Beans 注入到 Tapestry 页面中 - Tapestry 4.0+ 风格 WebWork 更多资源 Portlet MVC框架 介绍 控制器 - MVC中的C 视图 - MVC中的V Web作用范围的Bean DispatcherPortlet ViewRendererServlet 控制器 AbstractController 和 PortletContentGenerator 其它简单的控制器 Command控制器 PortletWrappingController 处理器映射 PortletModeHandlerMapping ParameterHandlerMapping PortletModeParameterHandlerMapping 增加 HandlerInterceptors HandlerInterceptorAdapter ParameterMappingInterceptor 视图和它们的解析 Multipart文件上传支持 使用 PortletMultipartResolver 处理表单里的文件上传 异常处理 Portlet应用的部署 整合 使用Spring进行远程访问与Web服务 简介 使用RMI暴露服务 使用RmiServiceExporter暴露服务 在客户端链接服务 使用Hessian或者Burlap通过HTTP远程调用服务 为Hessian和co.配置DispatcherServlet 使用HessianServiceExporter暴露你的bean 在客户端连接服务 使用Burlap 对通过Hessian或Burlap暴露的服务使用HTTP Basic认证 使用HTTP调用器暴露服务 Exposing the service object 在客户端连接服务 Web Services 使用JAX-RPC暴露基于servlet的web服务 使用JAX-RPC访问web服务 注册JAX-RPC Bean映射 注册自己的JAX-RPC 处理器 使用JAX-WS暴露基于servlet的web服务 使用JAX-WS暴露单独web服务 使用Spring支持的JAX-WS RI来暴露服务 使用JAX-WS访问web服务 使用XFire来暴露Web服务 JMS 服务端配置 客户端配置 对远程接口不提供自动探测实现 在选择这些技术时的一些考虑 Enterprise Java Beans (EJB) 集成 简介 访问EJB 概念 访问本地的无状态Session Bean(SLSB) 访问远程SLSB Accessing EJB 2.x SLSBs versus EJB 3 SLSBs 使用Spring提供的辅助类实现EJB组件 EJB 2.x base classes EJB 3 注入拦截 JMS (Java Message Service) 简介 使用Spring JMS JmsTemplate 连接工厂 目的地管理 消息侦听容器 SimpleMessageListenerContainer DefaultMessageListenerContainer ServerSessionMessageListenerContainer 事务管理 发送消息 使用消息转换器 SessionCallback 和 ProducerCallback 接收消息 同步接收 异步接收 - 消息驱动的POJO SessionAwareMessageListener接口 MessageListenerAdapter 事务中的消息处理 JCA消息端点的支持 JMS命名空间支持 JMX 介绍 将Bean暴露为JMX 创建MBeanServer 重用原有的MBeanServer 延迟初始化的MBean MBean的自动注册 控制注册行为 控制Bean的管理接口 MBeanInfoAssembler接口 使用源码级元数据 使用JDK 5.0的注解 源代码级的元数据类型 AutodetectCapableMBeanInfoAssembler接口 用Java接口定义管理接口 使用MethodNameBasedMBeanInfoAssembler 控制Bean的ObjectName 从Properties读取Properties 使用MetadataNamingStrategy <context:mbean-export/>元素 JSR-160连接器 服务器端连接器 客户端连接器 基于Burlap/Hessian/SOAP的JMX 通过代理访问MBean 通知 为通知注册监听器 发布通知 更多资源 JCA CCI 简介 配置CCI 连接器配置 在Spring中配置ConnectionFactory 配置CCI连接 使用一个 CCI 单连接 使用Spring的 CCI访问支持 记录转换 CciTemplate类 DAO支持 自动输出记录生成 总结 直接使用一个CCI Connection接口和Interaction接口 CciTemplate 使用示例 建模CCI访问为操作对象 MappingRecordOperation MappingCommAreaOperation 自动生成输出记录 总结 MappingRecordOperation 使用示例 MappingCommAreaOperation 使用示例 事务 Spring邮件抽象层 简介 使用Spring邮件抽象 MailSender 和 SimpleMailMessage 的基本用法 使用 JavaMailSender 和 MimeMessagePreparator 使用MimeMessageHelper 发送附件和嵌入式资源(inline resources) 附件 内嵌资源 使用模板来创建邮件内容 一个基于Velocity的示例 Spring中的定时调度(Scheduling)和线程池(Thread Pooling) 简介 使用OpenSymphony Quartz 调度器 使用JobDetailBean 使用 MethodInvokingJobDetailFactoryBean 使用triggers和SchedulerFactoryBean来包装任务 使用JDK Timer支持类 创建定制的timers 使用 MethodInvokingTimerTaskFactoryBean类 最后:使用TimerFactoryBean来设置任务 SpringTaskExecutor抽象 TaskExecutor接口 TaskExecutor类型 使用TaskExecutor 动态语言支持 介绍 第一个示例 定义动态语言支持的bean 公共概念 <lang:language/> 元素 Refreshable bean 内置动态语言源文件 理解dynamic-language-backed bean上下文中的构造器注入 JRuby beans Groovy beans 通过回调定制Groovy对象 BeanShell beans 场景 Spring MVC控制器的脚本化 Validator的脚本化 Bits and bobs AOP - 通知脚本化bean 作用域 更多的资源 注解和源代码级的元数据支持 简介 Spring的元数据支持 注解 @Required Spring中的其它@Annotations Jakarta Commons Attributes集成 元数据和Spring AOP自动代理 基本原理 声明式事务管理 示例程序 演示案例 介绍 使用动态语言实现的Spring MVC控制器 构建与部署 使用SimpleJdbcTemplate和@Repository实现DAO 域对象 Data Access Object 构建 XML Schema-based configuration Introduction XML Schema-based configuration Referencing the schemas The util schema <util:constant/> Setting a bean property or constructor arg from a field value <util:property-path/> Using <util:property-path/> to set a bean property or constructor-argument <util:properties/> <util:list/> <util:map/> <util:set/> The jee schema <jee:jndi-lookup/> (simple) <jee:jndi-lookup/> (with single JNDI environment setting) <jee:jndi-lookup/> (with multiple JNDI environment settings) <jee:jndi-lookup/> (complex) <jee:local-slsb/> (simple) <jee:local-slsb/> (complex) <jee:remote-slsb/> The lang schema The jms schema The tx (transaction) schema The aop schema The context schema <property-placeholder/> <annotation-config/> <component-scan/> <load-time-weaver/> <spring-configured/> <mbean-export/> The tool schema The beans schema Setting up your IDE Setting up Eclipse Setting up IntelliJ IDEA Integration issues XML parsing errors in the Resin v.3 application server Extensible XML authoring Introduction Authoring the schema Coding a NamespaceHandler Coding a BeanDefinitionParser Registering the handler and the schema 'META-INF/spring.handlers' 'META-INF/spring.schemas' Using a custom extension in your Spring XML configuration Meatier examples Nesting custom tags within custom tags Custom attributes on 'normal' elements Further Resources spring-beans-2.0.dtd spring.tld Introduction The bind tag The escapeBody tag The hasBindErrors tag The htmlEscape tag The message tag The nestedPath tag The theme tag The transform tag spring-form.tld Introduction The checkbox tag The checkboxes tag The errors tag The form tag The hidden tag The input tag The label tag The option tag The options tag The password tag The radiobutton tag The radiobuttons tag The select tag The textarea tag Spring 2.5开发手册中文化项目 声明 致谢 参与人员 项目历程
文字

6.8. 在Spring应用中使用AspectJ

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

Spring提供了一个小巧的AspectJ aspect library,你可以在程序发行版本中单独使用 spring-aspects.jar文件,并将其加入到classpath下以使用其中的切面。 第 6.8.1 节 “在Spring中使用AspectJ进行domain object的依赖注入”和第 6.8.2 节 “Spring中其他的AspectJ切面” 讨论了该库以及如何使用该库。 第 6.8.3 节 “使用Spring IoC来配置AspectJ的切面”讨论了如何对通过AspectJ compiler织入的AspectJ切面进行依赖注入。 最后第 6.8.4 节 “在Spring应用中使用AspectJ加载时织入(LTW)”介绍了使用AspectJ的Spring应用程序如何进行加载期织入(load-time weaving)。

6.8.1. 在Spring中使用AspectJ进行domain object的依赖注入

Spring容器对application context中定义的bean进行实例化和配置。同样也可以通过bean factory 来为一个已经存在且已经定义为spring bean的对象应用所包含的配置信息。 spring-aspects.jar中包含了一个annotation-driven的切面, 提供了能为任何对象进行依赖注入的能力。这样的支持旨在为 脱离容器管理而创建的对象进行依赖注入。领域对象经常处于这样的情形: 它们可能是通过new操作符创建的对象,也可能是由ORM工具查询数据库所返回的结果。

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

package com.xyz.myapp.domain;
                
                import org.springframework.beans.factory.annotation.Configurable;
                
                @Configurable
                public class Account {
                // ...
            }

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

<bean class="com.xyz.myapp.domain.Account" scope="prototype">
                <property name="fundsTransferService" ref="fundsTransferService"/>
            </bean>

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

package com.xyz.myapp.domain;
                
                import org.springframework.beans.factory.annotation.Configurable;
                
                @Configurable("account")
                public class Account {
                // ...
            }

Spring会查找名字为"account"的bean定义,并使用它作定义来配置一个新的 Account实例。

你也可以使用自动装配来避免手工指定原型定义的名字。只要设置@Configurable 注解中的autowire属性就可以让Spring进行自动装配: 指定@Configurable(autowire=Autowire.BY_TYPE)或者 @Configurable(autowire=Autowire.BY_NAME可以让自动装配分别按照类型或名字进行。 作为另外一种选择,在Spring2.5中最好是在域或方法级使用@Autowired@Resource为你的@Configurable beans指定 明确的、注解驱动的依赖注入。(详情请参看第 3.11 节 “基于注解(Annotation-based)的配置”)

最后,你可以通过使用dependencyCheck 属性,让Spring对新创建和配置的对象的对象引用进行 依赖检查(例如:@Configurable(autowire=Autowire.BY_NAME,dependencyCheck=true))。 如果这个属性设置为true,Spring会在配置结束后校验(除了primitives和collections类型) 所有的属性是否都被设置。

仅仅使用注解并没有做任何事情。但是spring-aspects.jar 中的AnnotationBeanConfigurerAspect会在注解存在时起作用。实质上切面指明: “在初始化一个由@Configurable 注解的新对象时, Spring按照注解中的属性来配置这个新创建的对象”。这种情况下,initialization 指新初始化的(比如用new初始化)的对象以及能进行反序列化的 Serializable对象(例如通过 readResolve()方法)。

注意

在上一段中一个关键的阶段就是“inessence”。多数情况下,“ 当从一个新对象初始化返回之后”的精确语义很不错...这种语境下, “初始化之后”的意思是依赖将在对象被构造之后注入 - 这意味着在类的构造器块中依赖将不可用。如果你希望它能在构造器代码块执行 之前被注入,并从而在构造器中使用它, 那么你需要在@Configurable接口声明上做类似的定义:

@Configurable(preConstruction=true)

你可以在 AspectJ Programming Guide一书的附录中 找到更多有关在AspectJ中各种切面类型的语义信息。

要实现上述的操作,已注解的类型必须由AspectJ weaver来织入 - 你可以使用一个构建时的ant/maven任务来完成 (参见AspectJ Development Environment Guide)或者使用加载时织入(参见 第 6.8.4 节 “在Spring应用中使用AspectJ加载时织入(LTW)”)。 类AnnotationBeanConfigurerAspect本身也需要Spring来配置(获得bean factory的引用,使用bean factory配置新的对象)。为此Spring的 context命名空间 定义了一个非常方便的标签。只要简单的在application context配置中包含下面的内容。

<context:spring-configured/>

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

<bean 
                class="org.springframework.beans.factory.aspectj.AnnotationBeanConfigurerAspect"
            factory-method="aspectOf"/>

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

<bean id="myService"
                class="com.xzy.myapp.service.MyService"
                depends-on="org.springframework.beans.factory.aspectj.AnnotationBeanConfigurerAspect">
                
                <!-- ... -->
                
            </bean>

6.8.1.1. @Configurable对象的单元测试

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

6.8.1.2. Working with multiple application contexts

6.8.1.2. Working with multiple application contexts

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

考虑一下典型的Spring web项目,一般都是由一个父application context定义大部分business service和 所需要的其他资源,然后每一个servlet拥有一个子application context定义。所有这些context共存于 同一个classloader体系下,因此AnnotationBeanConfigurerAspect仅保持 一个对context的引用。在这样的情况下,我们推荐在父application context中定义 <aop:spring-configured/> 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.8.2. Spring中其他的AspectJ切面

除了@Configurable切面, spring-aspects.jar包含了一个AspectJ切面可以用来为 那些使用了@Transactional注解的类型和方法驱动Spring事务管理。 提供这个的主要目的是有些用户希望脱离Spring容器使用Spring的事务管理。

解析@Transactional注解的切面是 AnnotationTransactionAspect。当使用这个切面时, 你必须注解这个实现类(和/或这个类中的方法),而不是 这个类实现的接口(如果有)。AspectJ允许在接口上注解的Java规则 不被继承

类之上的一个@Transactional注解为该类中任何 public操作的执行指定了默认的事务语义。

类内部方法上的一个@Transactional注解会覆盖类注解(如果存在) 所给定的默认的事务语义。具有public、protected和default修饰符的方法都可以被注解。 直接注解protected和default方法是让这个操作的执行获得事务划分的唯一途径。

对于AspectJ程序员,希望使用Spring管理配置和事务管理支持,不过他们不想(或者不能)使用注解, spring-aspects.jar也包含了一些抽象 切面供你继承来提供你自己的切入点定义。参见AbstractBeanConfigurerAspectAbstractTransactionAspect的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.8.3. 使用Spring IoC来配置AspectJ的切面

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

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

<bean id="profiler" class="com.xyz.profiler.Profiler"
                factory-method="aspectOf">
                <property name="profilingStrategy" ref="jamonProfilingStrategy"/>
            </bean>

non-singleton切面的配置稍难一点,然而它可以通过定义一个bean原型定义并且使用 spring-aspects.jar中的@Configurable支持, 当切面实例由AspectJ runtime创建后进行配置。

如果你希望一些@AspectJ切面使用AspectJ来织入(例如使用load-time织入domain object) 而另一些@AspectJ切面使用Spring AOP,并且这些切面都由Spring来管理,那你就需要告诉Spring AOP @AspectJ自动代理支持那些切面需要被自动代理。你可以通过在 <aop:aspectj-autoproxy>声明中使用一个或多个 <include/>元素。每个元素指定了一种命名格式, 只有bean命名至少符合其中一种情况下才会使用Spring AOP自动代理配置:

<aop:aspectj-autoproxy>
                <aop:include name="thisBean"/>
                <aop:include name="thatBean"/>
            </aop:aspectj-autoproxy>

注意

不要被<aop:aspectj-autoproxy/>元素的名字所误导: 用它会导致Spring AOP 代理的创建。在这中只是使用@AspectJ 类型的切面声明,但并不会涉及AspectJ运行时。

6.8.4. 在Spring应用中使用AspectJ加载时织入(LTW)

加载时织入(Load-time weaving(LTW))指的是在虚拟机载入字节码文件时动态织入AspectJ切面。 本 节关注于在Spring Framework中特的定context下配置和使用LTW:并没有LTW的介绍。 关于LTW和仅使用AspectJ配置LTW的详细信息(根本不涉及Spring),请查看 LTW section of the AspectJ Development Environment Guide。

Spring框架的值添加为AspectJ LTW在动态织入过程中提供了更细粒度的控制。使用Java(5+)的代理 能使用一个叫‘Vanilla’的AspectJ LTW,这需要在启动JVM的时候将某个VM参数设置为开。 这种JVM范围的设置在一些情况下或许不错,但通常情况下显得有些粗颗粒。而用Spring的LTW能让你在 per-ClassLoader的基础上打开LTW, 这显然更加细粒度并且对“单JVM多应用”的环境更具意义(例如在一个典型应用服务器环境中一样)。

另外,在某些环境下,这能让你使用LTW而 不对应用服务器的启动脚本做任何改动,不然则需要添加 -javaagent:path/to/aspectjweaver.jar或者(以下将会提及的)-javaagent:path/to/spring-agent.jar。 开发人员只需简单修改应用上下文的一个或几个文件就能使用LTW,而不需依靠那些管理着部署配置 比如启动脚本的系统管理员。

经过以上讲解之后,先让我们来过一遍一个使用Spring的AspectJ LTW的快速示例,接着是一个 有对元素详细讲解的示例。如果想要一个完整的示例,请参看Petclinic(宠物诊所)的应用实例。

6.8.4.1. 第一个例子

假设你是一个应用开人员,被指派诊断一个系统的若干性能问题。与其拿出性能分析工具, 我们不如开启一个简单的分析切面,使我们能很快地得到一些性能指标,这样我们就能马上 针对特定区域使用一些较细粒度的分析工具。

这就是一个分析切面。没什么特别的,只是一个快餐式的基于时间的模拟分析器, 使用类@AspectJ风格的切面声明。

package foo;
                    
                    import org.aspectj.lang.ProceedingJoinPoint;
                    import org.aspectj.lang.annotation.Aspect;
                    import org.aspectj.lang.annotation.Around;
                    import org.aspectj.lang.annotation.Pointcut;
                    import org.springframework.util.StopWatch;
                    import org.springframework.core.annotation.Order;
                    
                    @Aspect
                    public class ProfilingAspect {
                    
                    @Around("methodsToBeProfiled()")
                    public Object profile(ProceedingJoinPoint pjp) throws Throwable {
                    StopWatch sw = new StopWatch(getClass().getSimpleName());
                    try {
                    sw.start(pjp.getSignature().getName());
                    return pjp.proceed();
                    } finally {
                    sw.stop();
                    System.out.println(sw.prettyPrint());
                    }
                    }
                    
                    @Pointcut("execution(public * foo..*.*(..))")
                    public void methodsToBeProfiled(){}
                    }
                

我们还需要创建一个“META-INF/aop.xml”文件,以告知AspectJ weaver 我们要把ProfilingAspect织入到类中。这个文件惯例,即在Java classpath中 出现一个文件称作“META-INF/aop.xml”是标准的AspectJ。

<!DOCTYPE aspectj PUBLIC
                    "-//AspectJ//DTD//EN" "http://www.eclipse.org/aspectj/dtd/aspectj.dtd">
                    <aspectj>
                    
                    <weaver>
                    
                    <!-- only weave classes in our application-specific packages -->
                    <include within="foo.*"/>
                    
                    </weaver>
                    
                    <aspects>
                    
                    <!-- weave in just this aspect -->        
                    <aspect name="foo.ProfilingAspect"/>
                    
                    </aspects>
                    
                </aspectj>

现在来看Spring特定的配置部分。我们需要配置一个LoadTimeWeaver (稍后会有解释,暂时不多深究)。当将一个或多个“META-INF/aop.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"
                    xmlns:context="http://www.springframework.org/schema/context"
                    xsi:schemaLocation="
                    http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
                    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd">
                    
                    <!-- a service object; we will be profiling it's methods -->
                    <bean id="entitlementCalculationService"
                    class="foo.StubEntitlementCalculationService"/>
                    
                    <!-- this switches on the load-time weaving -->
                    <context:load-time-weaver/>
                    
                </beans>

现在万事俱备 - 切面,META-INF/aop.xml文件,以及Spring的配置 - 让我们创建一个带有main(..)方法的简单驱动类来演示LTW的作用吧。

package foo;
                    
                    import org.springframework.context.support.ClassPathXmlApplicationContext;
                    
                    public final class Main {
                    
                    public static void main(String[] args) {
                    
                    ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml", Main.class);
                    
                    EntitlementCalculationService entitlementCalculationService
                    = (EntitlementCalculationService) ctx.getBean("entitlementCalculationService");
                    
                    // the profiling aspect is 'woven' around this method execution
                    entitlementCalculationService.calculateEntitlement();
                    }
                }

最后还有一件事要做。此节之前的介绍说过可以有选择性的基于Spring的 per-ClassLoader来启动LTW,而且的确如此。不过,对此例来说, 我们将使用Java代理(由Spring提供)来启动LTW。这个就是用以运行上面Main 类的命令行语句:

java -javaagent:C:/projects/foo/lib/global/spring-agent.jar foo.Main

-javaagent是一个Java 5+标记,用来指定和激活 使JVM上的程序运行的代理。Spring框架装载了一个InstrumentationSavingAgent 代理,在上面的例子中被作为了-javaagent参数的值打包在 spring-agent.jar中。

Main程序运行的输出如下所示。(我已经在 calculateEntitlement()的实现中插入了Thread.sleep(..) 语句,以免让模拟分析器获取0毫秒 - 这里的01234毫秒并非是AOP引入的系统开销。)

Calculating entitlement
                    
                    StopWatch 'ProfilingAspect': running time (millis) = 1234
                    ------ ----- ----------------------------
                    ms     %     Task name
                    ------ ----- ----------------------------
                01234  100%  calculateEntitlement

因为这个LTW使用成熟的AspectJ,我们并不局限于通知Spring beans的方法;接下来这个稍有变化的 Main程序将生成同样的结果。

package foo;
                    
                    import org.springframework.context.support.ClassPathXmlApplicationContext;
                    
                    public final class Main {
                    
                    public static void main(String[] args) {
                    
                    new ClassPathXmlApplicationContext("beans.xml", Main.class);
                    
                    EntitlementCalculationService entitlementCalculationService =
                    new StubEntitlementCalculationService();
                    
                    // the profiling aspect will be 'woven' around this method execution
                    entitlementCalculationService.calculateEntitlement();
                    }
                }

注意以上程序我们只是引导了Spring容器,然后完全在Spring上下文之外创建了一个 StubEntitlementCalculationService的实例...分析通知仍然得到织入。

上面的例子虽然简单了些,但Spring中基本的LTW支持都已介绍完了, 此节余下内容将对使用这些配置和用法背后的理由作详细解释。

注意

ProfilingAspect在此例中虽然基本但是颇为有用。这是一个很好的开发时切面的例子,开发者可以在开发过程中使用它(废话), 然后也能从已部署到UAT或者生产环境的应用中轻易的脱离。

6.8.4.2. 切面

你在LTW中使用的切面必须是AspectJ切面。你可以使用AspectJ语言或者类@AspectJ风格来编写你的切面。 后一种方式当然只能在Java 5+中使用,但它说明了你的切面可以同时对AspectJ和Spring AOP切面有效。 此外,编译后的切面类需要被注册到classpath下。

6.8.4.3. 'META-INF/aop.xml'

AspectJ LTW的基础设施是用一个或多个位于Java classpath上的(可以是直接的文件形式, 也可以是更典型的jar包形式)META-INF/aop.xml文件配置起来的。

有关文件的结构和内容都在AspectJ的参考文档中有详细介绍,有兴趣的读者 请参考这些资源。(很庆幸这一节比较简短,但aop.xml文件 是100% AspectJ的 - 没有任何使用Spring特定的信息或语义,因此我也没有什么可贡献的。 与其重写这些已由AspectJ开发者提供的令人满意的章节,我不如领你到这里。)

6.8.4.4. 相关类库(JARS)

你至少需要以下类库来让Spring框架支持AspectJ LTW:

  1. spring.jar(2.5或更高版本)

  2. aspectjrt.jar (1.5或更高版本)

  3. aspectjweaver.jar (1.5或更高版本)

如果你正在使用 由Spring提供的代理来激活检测(instrumentation)功能,你会需要:

  1. spring-agent.jar

6.8.4.5. Spring配置

Spring LTW功能的关键组件是LoadTimeWeaver接口 (在org.springframework.instrument.classloading包中), 以及Spring分发包中大量的实现。LoadTimeWeaver的实现负责 在运行时把一个或多个java.lang.instrument.ClassFileTransformers类添加到 ClassLoader中,这能产生各种各样有趣的应用,LTW切面恰好便是其中之一。

提示

如果你对运行时类文件变换的思想还不熟悉,推荐你在继续之前阅读 java.lang.instrument包的Javadoc API文档。 这其实并不难-反而有些恼人-因为有用的文件并不多...关键的接口和类都将会在此节呈现给你。

用XML为ApplicationContext配置一个 LoadTimeWeaver简单得只需要添加一行。 (请注意几乎肯定你需要使用ApplicationContext作为你的 Spring容器 - 一般来说只有BeanFactory是不够的, 因为LTW功能需要用到BeanFactoryPostProcessors。)

当要使用Spring框架的LTW功能时,你需要配置一个LoadTimeWeaver, 一般可以用<context:load-time-weaver/>元素来完成。 下面为一个有效的使用默认设置的<context:load-time-weaver/>定义。

<?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:context="http://www.springframework.org/schema/context"
                    xsi:schemaLocation="
                    http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
                    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd">
                    
                    <context:load-time-weaver/>
                    
                </beans>

上面<context:load-time-weaver/> bean的定义会自动为你定义和注册若干 特定LTW的基础设施beans,比如一个LoadTimeWeaver 和一个AspectJWeavingEnabler。请注意 <context:load-time-weaver/>是怎样在context 命名空间下被定义的;还要注意被引用的XML Schema文件只在Spring 2.5或更高版本中才可用。

上面的配置为你定义并注册了一个默认的LoadTimeWeaver bean。 默认的LoadTimeWeaver是一个 DefaultContextLoadTimeWeaver类,它更倾向于去装饰一个能自动检测的LoadTimeWeaver类:LoadTimeWeaver 的确切类型会根据你的运行时环境“自动检测”出来(概述如下表)。

表 6.1. DefaultContextLoadTimeWeaver LoadTimeWeaversDefaultContextLoadTimeWeaver类和LoadTimeWeavers接口

运行时环境 LoadTimeWeaver的接口实现

BEA's Weblogic 10环境下

WebLogicLoadTimeWeaver

Oracle's OC4J环境下

OC4JLoadTimeWeaver

GlassFish环境下

GlassFishLoadTimeWeaver

以SpringInstrumentationSavingAgent

启动的JVM中

(java -javaagent:path/to/spring-agent.jar)

InstrumentationLoadTimeWeaver

不过,我们更希望这些类加载器能遵循共同的规范 (例如适用TomcatInstrumentableClassLoader和Resin)

ReflectiveLoadTimeWeaver


请注意当使用DefaultContextLoadTimeWeaver时只有 LoadTimeWeavers实现类能进行自动检测: 当然,你也可以通过指定将类的完全限定名作为<context:load-time-weaver/> 元素中weaver-class属性的值 来指定究竟想使用哪个LoadTimeWeaver的实现。如下例:

<?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:context="http://www.springframework.org/schema/context"
                    xsi:schemaLocation="
                    http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
                    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd">
                    
                    <context:load-time-weaver
                    weaver-class="org.springframework.instrument.classloading.ReflectiveLoadTimeWeaver"/>
                    
                </beans>

<context:load-time-weaver/>元素上定义和注册的 LoadTimeWeaver接口可以在Spring容器中以 loadTimeWeaver名字找到。 记住LoadTimeWeaver接口只是作为Spring LTW基础设施的一个机制 用来添加一个或多个ClassFileTransformers的。 ClassFileTransformer类实际是利用 ClassPreProcessorAgentAdapter类(包含在 org.aspectj.weaver.loadtime中)来进行LTW的。 有关ClassPreProcessorAgentAdapter的细节请参见 类级别的javadoc,织入实际怎样生效的具体内容已经超出本节讨论范围。

让我们来讨论<context:load-time-weaver/>的最后一个属性: aspectj-weaving。 这是一个简单的LTW开关,就这么简单。 它可以接受如下所述的三种值,如果不显示设置此属性则其默认值为autodetect

表 6.2. aspectj-weaving属性值

属性值 注释

on

AspectJ织入功能开启,切面将会在加载时适当时机被织入。

off

LTW功能关闭...不会在加载时织入切面。

autodetect

如果Spring LTW基础设施能找到至少一个META-INF/aop.xml 文件,那么AspectJ织入将会开启,否则关闭。此为默认值。


6.8.4.6. 特定环境的配置

这最后一节包括所有你在诸如应用服务器和web容器中使用Spring的LTW功能时需要的额外设置和配置。

6.8.4.6.1. 通用Java应用

你可能在各种Java应用中通过使用由Spring提供的检测代理启用Spring的LTW功能 (独立应用或者基于应用服务器的应用)。这样的话,可以通过指定 -javaagent:path/to/spring-agent.jar选项来启动虚拟机。 请注意这需要修改虚拟机的启动脚本,但在某些应用服务器环境下是禁止这么做的 (这取决于你的操作策略)。

6.8.4.6.2. Tomcat

对于部署在Apache Tomcat 5.0或更高版本上的web应用,Spring将一个 TomcatInstrumentableClassLoader注册成为web应用的类加载器。 必须的Tomcat设置如下所示,你可以把它放在Tomcat WAR包根目录下的核心文件 server.xml中或放到应用特定的META-INF/context.xml文件中。 Spring的spring-tomcat-weaver.jar需要被包含到Tomcat 的common lib路径下以确保设置生效。

<Context path="/myWebApp" docBase="/my/webApp/location">
                        <Loader loaderClass="org.springframework.instrument.classloading.tomcat.TomcatInstrumentableClassLoader"
                        useSystemClassLoaderAsParent="false"/>
                        </Context>
                    

注意:当使用LTW时,我们一般推荐使用Tomcat 5.5.20或更高版本。 先前的版本对定制的ClassLoader设置会产生问题。

另外,请考虑使用在Tomcat启动脚本中(见上面)指定由Spring提供的通用虚拟机代理。 这样才能使检测功能在所有已部署的web应用中可用,无论其上运行的是哪种类加载器。

有关更多基于Tomcat织入设置的详细讨论,请参考讨论各种不同Tomcat版本内容的 第 12.6.1.3.1 节 “Tomcat(5.0以上)加载时的织入配置”一节。虽然本节主要关注于 JPA persistence提供者的设置,但也谈到了Tomcat各种特定设置适用于一般加载时织入的情况。

6.8.4.6.3. WebLogic, OC4J, Resin, GlassFish

BEA WebLogic(版本10或更高),Oracle的JavaEE容器(OC4J 10.1.3.1或更高)以及 Resin(版本3.1或更高)提供具有本地检测能力的类加载器。 Srping的原生LTW利用这些类加载器来激活AspectJ织入。你可以通过简单地激活之前提到的 context:load-time-weaver来启动LTW功能。具体来说,即你 需要通过修改启动脚本来添加 -javaagent:path/to/spring-agent.jar

GlassFish同样也提供了检测能力的类加载器,不过只能在它的EAR环境下使用。 对于GlassFish的web应用,可以使用跟上面tomcat相同的设置。

上一篇: 下一篇: