- 浏览: 1020671 次
- 性别:
- 来自: 杭州
-
文章分类
- 全部博客 (826)
- 硬件 (8)
- 软件 (24)
- 软件工程 (34)
- JAVA (229)
- C/C++/C# (77)
- JavaScript (8)
- PHP (1)
- Ruby (3)
- MySQL (14)
- 数据库 (19)
- 心情记事 (12)
- 团队管理 (19)
- Hadoop (1)
- spring (22)
- mybatis(ibatis) (7)
- tomcat (16)
- velocity (0)
- 系统架构 (6)
- JMX (8)
- proxool (1)
- 开发工具 (16)
- python (10)
- JVM (27)
- servlet (5)
- JMS (26)
- ant (2)
- 设计模式 (5)
- 智力题 (2)
- 面试题收集 (1)
- 孙子兵法 (16)
- 测试 (1)
- 数据结构 (7)
- 算法 (22)
- Android (11)
- 汽车驾驶 (1)
- lucene (1)
- memcache (12)
- 技术架构 (7)
- OTP-Erlang (7)
- memcached (17)
- redis (20)
- 浏览器插件 (3)
- sqlite (3)
- Heritrix (9)
- Java线程 (1)
- scala (0)
- Mina (6)
- 汇编 (2)
- Netty (15)
- libevent (0)
- CentOS (12)
- mongod (5)
- mac os (0)
最新评论
-
kingasdfg:
你这里面存在一个错误添加多个任务 应该是这样的 /** * ...
Quartz的任务的临时启动和暂停和恢复【转】 -
kyzeng:
纠正一个错误,long型对应的符号是J,不是L。
Jni中C++和Java的参数传递 -
zhaohaolin:
抱歉,兄弟,只是留下作记录,方便学习,如果觉得资料不好,可以到 ...
netty的个人使用心得【转】 -
cccoooccooco:
谢谢!自己一直以为虚机得使用网线才可以与主机连接呢。。
主机网卡无网线连接与虚拟机通信 -
yuqilin001:
要转别人的东西,请转清楚点嘛,少了这么多类,误人子弟
netty的个人使用心得【转】
原理
AOP(Aspect Oriented Programming),也就是面向方面编程的技术。AOP基于IoC基础
,是对OOP的有益补充。
AOP将应用系统分为两部分,核心业务逻辑(Core business
concerns)及横向的通用逻辑,也就是所谓的方面Crosscutting enterprise
concerns,例如,所有大中型应用都要涉及到的持久化管理(Persistent)、事务管理(Transaction
Management)、安全管理(Security)、日志管理(Logging)和调试管理(Debugging)等。
AOP正在成为软件开发
的下一个光环。使用AOP,你可以将处理aspect的代码
注入主程序,通常主程序的主要目的并不在于处理这些aspect。AOP可以防止代码混乱。
Spring framework是很有前途的AOP技术。作为一种非侵略性的、轻型的AOP
framework,你无需使用预编译器或其他的元标签,便可以在Java程序中使用它。这意味着开发团队里只需一人要对付AOP
framework,其他人还是像往常一样编程。
AOP概念
让我们从定义一些重要的AOP概念开始。
— 方面(Aspect):一个关注点的模块化,这个关注点实现可能另外横切多个对象。事务管理是J2EE应用中一个很好的横切关注点例子。方面用Spring的Advisor或拦截器实现。
— 连接点(Joinpoint):程序执行过程中明确的点,如方法的调用或特定的异常被抛出。
— 通知(Advice):在特定的连接点,AOP框架执行的动作。各种类型的通知包括“around”、“before”和“throws”通知。通知类型将在下面讨论。许多AOP框架包括Spring都是以拦截器做通知模型
,维护一个“围绕”连接点的拦截器链。
— 切入点(Pointcut):指定一个通知将被引发的一系列连接点的集合。AOP框架必须允许开发者指定切入点,例如,使用正则表达式。
— 引入(Introduction):添加方法或字段到被通知的类。Spring允许引入新的接口到任何被通知的对象。例如,你可以使用一个引入使任何对象实现IsModified接口,来简化缓存
。
— 目标对象(Target Object):包含连接点的对象,也被称作被通知或被代理对象。
— AOP代理(AOP Proxy):AOP框架创建的对象,包含通知。在Spring中,AOP代理可以是JDK动态
代理或CGLIB代理。
— 编织(Weaving):组装方面来创建一个被通知对象。这可以在编译时完成(例如使用AspectJ编译器),也可以在运行时完成。Spring和其他纯Java AOP框架一样,在运行时完成织入。
各种通知类型包括:
— Around通知:包围一个连接点的通知,如方法调用。这是最强大的通知。Aroud通知在方法调用前后完成自定义的行为,它们负责选择
继续执行连接点或通过返回它们自己的返回值或抛出异常来短路执行。
— Before通知:在一个连接点之前执行的通知,但这个通知不能阻止连接点前的执行(除非它抛出一个异常)。
— Throws通知:在方法抛出异常时执行的通知。Spring提供强制类型的Throws通知,因此你可以书写代码捕获感兴趣的异常(和它的子类),不需要从Throwable或Exception强制类型转换。
— After returning通知:在连接点正常完成后执行的通知,例如,一个方法正常返回,没有抛出异常。
Around通知是最通用的通知类型。大部分基于拦截的AOP框架(如Nanning和Jboss 4)只提供Around通知。
如同AspectJ,Spring提供所有类型的通知,我们推荐你使用最为合适的通知类型来实现需要的行为。例如,如果只是需要用一个方法的返回值来
更新缓存,你最好实现一个after
returning通知,而不是around通知,虽然around通知也能完成同样的事情。使用最合适的通知类型使编程模型变得简单,并能减少潜在错
误。例如,你不需要调用在around通知中所需使用的MethodInvocation的proceed()方法,因此就调用失败。
切入点的概念是AOP的关键,它使AOP区别于其他使用拦截的技术。切入点使通知独立于OO的层次选定目标。例如,提供声明式事务管理的around通知可以被应用到跨越多个对象的一组方法上。 因此切入点构成了AOP的结构要素。
拦截器(也称拦截机)
拦截机 (Interceptor), 是 AOP (Aspect-Oriented Programming)
的另一种叫法。AOP本身是一门语言,只不过我们使用的是基于JAVA的集成到Spring 中的
SpringAOP。同样,我们将通过我们的例子来理解陌生的概念。
接口类
Java代码
package com.test.TestSpring3; public interface UserService // 被拦截的接口 { public void printUser(String user); }
实现类
Java代码
package com.test.TestSpring3; public class UserServiceImp implements UserService // 实现UserService接口 { public void printUser(String user) ...{ System.out.println("printUser user:" + user);// 显示user } }
AOP拦截器
package com.test.TestSpring3; import org.aopalliance.intercept.MethodInterceptor; import org.aopalliance.intercept.MethodInvocation; public class UserInterceptor implements MethodInterceptor // AOP方法拦截器 { public Object invoke(MethodInvocation arg0) throws Throwable ...{ try ...{ if (arg0.getMethod().getName().equals("printUser")) // 拦截方法是否是UserService接口的printUser方法 ...{ Object[] args = arg0.getArguments();// 被拦截的参数 System.out.println("user:" + args[0]); arg0.getArguments()[0] = "hello!";// 修改被拦截的参数 } System.out.println(arg0.getMethod().getName() + "---!"); return arg0.proceed();// 运行UserService接口的printUser方法 } catch (Exception e) ...{ throw e; } } }
测试类
Java代码
package com.test.TestSpring3; import org.spring framework.beans.factory.BeanFactory; import org.springframework.beans.factory.xml .XmlBeanFactory; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.context.support.FileSystemXmlApplicationContext; import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.Resource; import org.springframework.web.context.support.WebApplicationContextUtils; public class TestInterceptor ...{ public static void main(String[] args) ...{ ApplicationContext ctx = new FileSystemXmlApplicationContext( "classpath:applicationContext.xml"); // ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml"); UserService us = (UserService) ctx.getBean("userService"); us.printUser("shawn"); } }
配置文件
Xml代码
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"> <beans> <bean id="userServiceImp" class="com.test.TestSpring3.UserServiceImp" /> <bean id="userInterceptor" class="com.test.TestSpring3.UserInterceptor" /> <bean id="userService" class="org.springframework.aop.framework.ProxyFactoryBean"> <!-- 代理接口 --> <property name="proxyInterfaces"> <value>com.test.TestSpring3.UserService</value> </property> <!-- 目标实现类 --> <property name="target"> <ref local="userServiceImp" /> </property> <!-- 拦截器 --> <property name="interceptorNames"> <list> <value>userInterceptor</value> </list> </property> </bean> </beans>
输出:
user:shawn
printUser---!
printUser user:hello!
结论:调用方法的时候 传入的值被拦截修改了.
拦截器中的事务管理(事务拦截机)
如果不采用拦截机的机制时,在使用JDBC
进行数据
库访问时,存在两种情况:
自动提交 这是JDBC驱动默认的模式,每次数据库操作(CRUD)成功完成后,都作为一个单独的事务自动提交,如果未成功完成,即抛出了 SQLException 的话,仅最近的一个操作将回滚。
非自动提交 这是想更好的控制事务时需要程序地方式进行控制:
在进行该事务单元的任何操作之前 setAutoCommit(false)
在成功完成事务单元后 commit()
在异常发生后 rollback()
自动提交模式是不被推荐的,因为每个操作都将产生一个事务点,这对于大的应用来说性能将受到影响;再有,对于常见的业务逻辑,这种模式显得无能为力。比如:
转帐,从A帐户取出100元,将其存入B帐户;如果在这两个操作之间发生了错误,那么用户
A将损失了100元,而本来应该给帐户B的,却因为失败给了银行。
所以,建议在所有的应用中,如果使用 JDBC 都将不得不采用非自动提交模式(你们要能发现了在我们的 JDBC 那个例子中,我们采用的就是自动提交模式,我们是为了把精力放在JDBC上,而不是事务处理上),即我们不得不在每个方法中:
Java代码
try { // 在获得连接后,立即通过调用 setAutoCommit(false) 将事务处理置为非自动提交模式 // Prepare Query to fetch the user Information pst = conn.prepareStatement(findByName); // ... conn.commit(); } catch(Exception ex) { conn.rollback(); throw ex; }finally { try { // Close Result Set and Statement if (rset != null) rset.close(); if (pst != null) pst.close(); } catch (Exception ex) { ex.printStackTrace(); throw new Exception("SQL Error while closing objects = " + ex.toString()); } }
这样代码在AOP的倡导者看来是“肮脏”的代码。他们认为,所有的与事务有关的方法都应当可以集中配置(见声明性事务控制),并自动拦截,程序应当关心他们的主要任务,即商业逻辑,而不应和事务处理的代码搅和在一起。
我先看看 Spring 是怎么做到拦截的:
Spring 内置支持的事务处理拦截机
这里因为要用到JpetStore项目中的代码,我们将 applicationContext.xml 全部内容列出:
<?xml version="1.0" encoding="UTF-8"?> <!-- - Application context definition for JPetStore's business layer. - Contains bean references to the transaction manager and to the DAOs in - dataAccessContext-local/jta.xml (see web.xml's "contextConfigLocation"). Jpetstore 的应用上下文定义,包含事务管理和引用了在 dataAccessContext-local/jta.xml(具体使用了哪个要看 web.xml 中的 'contextConfigLocation' 的配置)中注册的DAO --> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd "> <!-- ========================= GENERAL DEFINITIONS ========================= --> <!-- Configurer that replaces ${...} placeholders with values from properties files 占位符的值将从列出的属性 文件中抽取出来 --> <!-- (in this case, mail and JDBC related properties) --> <bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> <property name="locations"> <list> <value>WEB-INF/mail.properties</value> <value>WEB-INF/jdbc.properties</value> </list> </property> </bean> <!-- MailSender used by EmailAdvice 指定用于发送邮件的 java mail 实现者,这里使用了 spring 自带的实现。此 bean 将被 emailAdvice 使用 --> <bean id="mailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl"> <property name="host" value="${mail.host}"/> </bean> <!-- ========================= BUSINESS OBJECT DEFINITIONS ======================== --> <!-- 不需要,因为被 SpringMVC 的实现使用 Generic validator for Account objects, to be used for example by the Spring web tier --> <bean id="accountValidator" class="org.springframework.samples.jpetstore.domain.logic.AccountValidator"/> <!-- 不需要,因为被 SpringMVC 的实现使用 Generic validator for Order objects, to be used for example by the Spring web tier --> <bean id="orderValidator" class="org.springframework.samples.jpetstore.domain.logic.OrderValidator"/> <!-- 主要的商业逻辑对象,即我们所说的门面对象 注入了所有的DAO,这些DAO是引用了 dataAccessContext-xxx.xml 中定义的DAO 门面对象中的所有方法的事务控制将通过下面的 aop:config 来加以控制 - JPetStore primary business object (default implementation). - Transaction advice gets applied through the AOP configuration below. --> <bean id="petStore" class="org.springframework.samples.jpetstore.domain.logic.PetStoreImpl"> <property name="accountDao" ref="accountDao"/> <property name="categoryDao" ref="categoryDao"/> <property name="productDao" ref="productDao"/> <property name="itemDao" ref="itemDao"/> <property name="orderDao" ref="orderDao"/> </bean> <!-- ========================= ASPECT CONFIGURATION ======================== --> <!-- AOP配置,用来控制哪些方法将需要进行事务处理,采用了AspectJ 的语法 --> <aop:config> <!-- This definition creates auto-proxy infrastructure based on the given pointcut, expressed in AspectJ pointcut language. Here: applying the advice named "txAdvice" to all methods on classes named PetStoreImpl. --> <!-- 指出在 PetStoreFacade 的所有方法都将采用 txAdvice(在紧接着的元素中定义了)事务方针,注意,我们这里虽然指定的是接口 PetStoreFacace, 但其暗示着其所有的实现类也将 同样具有这种性质,因为本身就是实现类的方法在执行的,接口是没有方法体的。 --> <aop:advisor pointcut="execution(* *..PetStoreFacade.*(..))" advice-ref="txAdvice"/> <!-- This definition creates auto-proxy infrastructure based on the given pointcut, expressed in AspectJ pointcut language. Here: applying the advice named "emailAdvice" to insertOrder(Order) method of PetStoreImpl --> <!-- 当执行 PetStoreFacade.insertOrder方法,该方法最后一个参数为Order类型时(其实我们的例子中只有一个 insertOrder 方法,但这告诉了我们,当我们的接口或类中有重载了的方法, 并且各个重载的方法可能使用不同的拦截机机制时,我们可以通过方法的参数加以指定),将执行emailAdvice(在最后定义的那个元素)--> <aop:advisor pointcut="execution(* *..PetStoreFacade.insertOrder(*..Order))" advice-ref="emailAdvice"/> </aop:config> <!-- 事务方针声明,用于控制采用什么样的事务策略 Transaction advice definition, based on method name patterns. Defaults to PROPAGATION_REQUIRED for all methods whose name starts with "insert" or "update", and to PROPAGATION_REQUIRED with read-only hint for all other methods. --> <tx:advice id="txAdvice"> <tx:attributes> <tx:method name="insert*"/> <tx:method name="update*"/> <tx:method name="*" read-only="true"/> </tx:attributes> </tx:advice> <!-- 拦截机,用于在适当的时机(通过AOP配置,如上面)在方法执行成功后发送邮件 AOP advice used to send confirmation email after order has been submitted --> <!-- --> <bean id="emailAdvice" class="org.springframework.samples.jpetstore.domain.logic.SendOrderConfirmationEmailAdvice"> <property name="mailSender" ref="mailSender"/> </bean> <!-- ========================= 忽略 REMOTE EXPORTER DEFINITIONS ======================== --> </beans>
这个配置比想象的要简单的多:
Xml代码
<SPAN style="FONT-SIZE: medium"><aop:config>
<!-- This definition creates auto-proxy infrastructure based on the
given pointcut, expressed in AspectJ pointcut language.
Here: applying the advice named "txAdvice" to all methods on classes named PetStoreImpl. 指出在 PetStoreFacade
的所有方法都将采用 txAdvice(在紧接着的元素中定义了)事务方针,注意,我们这里虽然指定的是接口 PetStoreFacace,
但其暗示着其所有的实现类也将同样具有这种性质,因为本身就是实现类的方法在执行的,接口是没有方法体的。 -->
<aop:advisor pointcut="execution(* *..PetStoreFacade.*(..))" advice-ref="txAdvice"/>
<!-- 其它拦截机-->
</aop:config>
</SPAN>
<aop:config>
<!-- This definition creates auto-proxy infrastructure based on the given pointcut, expressed in AspectJ pointcut language.
Here: applying the advice named "txAdvice" to all methods on classes named PetStoreImpl. 指出在 PetStoreFacade
的所有方法都将采用 txAdvice(在紧接着的元素中定义了)事务方针,注意,我们这里虽然指定的是接口 PetStoreFacace,
但其暗示着其所有的实现类也将同样具有这种性质,因为本身就是实现类的方法在执行的,接口是没有方法体的。 -->
<aop:advisor pointcut="execution(* *..PetStoreFacade.*(..))" advice-ref="txAdvice"/>
<!-- 其它拦截机-->
</aop:config>
1. 所有的拦截机配置都放在 <aop:config> 配置元素中.
2. 下面还是需要理解一下几个有关AOP的专用名词,不过,是挺抽象的,最好能会意出其的用意
pointcut 切入点,比如:updateAccount
方法需要进行事务管理,则这个切入点就是“执行方法体”(execution)。Spring 所有支持的切入点类型在都在 Spring
reference: 6.2.3.1. Supported Pointcut Designators 中列出了。
advice 要对这个切入点进行什么操作,比如事务控制
advisor Spring 特有的概念,将上两个概念合到一个概念中来,即一个 advisor 包含了一个切入点及对这个切入点所实施的操作。
因为 方法执行切入点 execution 为最常见的切入点类型,我们着重介绍一下,execution 的完全形式为:
execution(modifiers-pattern? ret-type-pattern declaring-type-pattern?
name-pattern(param-pattern) throws-pattern?)这是一个正则表达式,其中由 '?'
结尾的部分是可选的。翻译过来就是:
执行(方法访问修饰符? 方法返回类型 声明类型? 方法名(方法参数类型) 抛出异常?)所有的这些都是用来定义执行切入点,即那些方法应该被侯选为切入点:
方法访问修饰符 即 public, private 等等
方法返回类型 即方法返回的类型,如 void, String 等等
声明类型 1.5的语法,现在可以先忽略它
方法名 方法的名字
方法参数类型 方法的参数类型
抛出异常 方法声明的抛出的异常
例如,所有dao代码被定义在包 com.xyz.dao 及子包 com.xyz.dao.hibernate
, 或者其它,如果还有的话,子包中, 里面定义的是提供DAO功能的接口或类,那么表达式:
execution(* com.xyz.dao..*.*(..))表示切入点为:执行定义在包 com.xyz.dao 及其子包(因为 .. 所致) 中的任何方法
详细情况可以参见 Spring refernce: 6.2.3.4. Examples
因此这个表达式为执行定义在类 PetStoreFacade 及其实现类中的所有方法,采取的动作定义在 txAdvice 中. 关于该 advice 的定义,(见声明性事务控制)一节
<aop:advisor pointcut="execution(* *..PetStoreFacade.*(..))" advice-ref="txAdvice"/>
Spring 自定拦截机
来为了进行事务控制,我们只需简单地配置几下,所有的工作都由 Spring
来做。这样固然很好,但有时我们需要有我们特有的控制逻辑。因为Spring
不可能包含所有人需要的所有拦截机。所以它提供了通过程序的方式加以定制的方式。我们的项目中就有这么一个拦截机,在用户确认付款后,将定单信息通过
email 的方式发送给注册用户的邮箱中。
<aop:config>
...
<!-- 当执行
PetStoreFacade.insertOrder方法,该方法最后一个参数为Order类型时(其实我们的例子中只有一个 insertOrder
方法,但这告诉了我们,当我们的接口或类中有重载了的方法, 并且各个重载的方法可能使用不同的拦截机机制时,我们可以通过方法的参数加以
指定),将执行emailAdvice(在最后定义的那个元素)-->
<aop:advisor pointcut="execution(* *..PetStoreFacade.insertOrder(*..Order))" advice-ref="emailAdvice"/>
</aop:config>红色的注释已经说的很清楚这个 Advisor 了,它的切入点(pointcut) 为
PetStoreFacade 的 void insertOrder(Order order) 方法,采取的动作为引用的 emailAdvice,
下面我们就来看看 emailAdvice:
<bean id="emailAdvice" class="org.springframework.samples.jpetstore.domain.logic.SendOrderConfirmationEmailAdvice">
<property name="mailSender" ref="mailSender"/>
</bean>它给了这个 advice 的实现类为 logic 包中 SendOrderConfirmationEmailAdvice, 该Bean 引用了我们前面定义的邮件发送器(一个 Spring 内置的邮件发送器).
下面看看这个实现类:
public class SendOrderConfirmationEmailAdvice implements AfterReturningAdvice, InitializingBean { // user jes on localhost private static final String DEFAULT_MAIL_FROM = "test@pprun.org"; private static final String DEFAULT_SUBJECT = "Thank you for your order!"; private final Log logger = LogFactory.getLog(getClass()); private MailSender mailSender; private String mailFrom = DEFAULT_MAIL_FROM; private String subject = DEFAULT_SUBJECT; public void setMailSender(MailSender mailSender) { this.mailSender = mailSender; } public void setMailFrom(String mailFrom) { this.mailFrom = mailFrom; } public void setSubject(String subject) { this.subject = subject; } public void throws Exception { if (this.mailSender == null) { throw new IllegalStateException("mailSender is required"); } } /** * * @param returnValue 被拦截的方法的返回值 * @param m 被拦截的方法的所有信息(Method类封装了这些信息) * @param args 被拦截的方法的所有参数组成的数组 * @param target 目标对象,对于方法执行来说,即是方法所在的类的实例(与 this 同,批当前对象) * @throws java.lang.Throwable */ public void afterReturning(Object returnValue, Method m, Object[] args, Object target) throws Throwable { // 我们被拦截的方法为 void insertOrder(Order order),方法只有一个参数,所以可知数据的第1个元素即是被传进的 order 对象 // 得到了order 对象,就可以将 order 对应的帐户名及帐单号发送到邮件中,以便确认无误。 Order order = (Order) args[0]; Account account = ((PetStoreFacade) target).getAccount(order.getUser().getUsername()); // don't do anything if email address is not set if (account.getEmail() == null || account.getEmail().length() == 0) { return; } StringBuffer text = new StringBuffer(); text.append("Dear ").append(account.getFirstname()). append(' ').append(account.getLastname()); text.append(", thank your for your order from JPetStore. " + "Please note that your order number is "); text.append(order.getId()); SimpleMailMessage mailMessage = new SimpleMailMessage(); mailMessage.setTo(account.getEmail()); mailMessage.setFrom(this.mailFrom); mailMessage.setSubject(this.subject); mailMessage.setText(text.toString()); try { this.mailSender.send(mailMessage); } catch (MailException ex) { // just log it and go on logger.warn("An exception occured when trying to send email", ex); } } }
1. 红色的内容即为反向注入的 mailSender 属性
2. 蓝色的内容为 Spring Bean 的一个通用的接口 InitializingBean ,实现类需要实现该接口定义的方法
afterPropertiesSet() ,该方法中一般是在Bean 被初始化后并设置了所有的 setter
注入后调用的。所以这里是保证邮件发送器配置正确。因为如果没有配置正确,下面的工作是无法进行的,所以与其等那时抛出异常,还不如早早地在部署时就告知
(通过抛出 IllegalStateException 来提示)
3. 绿色的内容为这个 Advise 的核心,即在切入点被切入后将采用的动作。因为 Advise
也同样有多种类型,比如我们这里的“方法正常返回”,“方法执行前”,“方法执行后”,“环绕在方法执行前后”,“方法抛出异常时”等等(详情参见
Spring Reference: 6.2.4. Declaring
advice)。但是我们的逻辑为在用户确认定单并且执行成功(所谓的成功是指将这一定单插入到了表 Order
中了)后,将发送一确认信。所以”方法正常返回“完全符合我们的要求。
接口AfterReturningAdvice 即是 Spring中表示”方法正常返回“ 这一语义的 Advice, 所以我们实现这个接口及其必须的方法 afterReturning.
方法代码的工作其实并不重要,只要我们理解这些“魔法”一样的技术后,实现代码是很简单的。值得提及的是这个方法的参数,这些参数是封装了切入点的所有信
息,请见上面的注释。在我们的实现中只使用了被拦截方法的参数,在复杂的 Advice 实现中可能会用到切入点所有信息。
发表评论
-
调试jdk中的源码,查看jdk局部变量
2013-06-15 23:30 1060调试jdk中的源码,查看jdk局部变量 2012-04 ... -
Eclipse快捷键 10个最有用的快捷键<转>
2013-04-11 23:28 1085Eclipse中10个最有用的快捷键组合 一个Eclip ... -
Lucene 3.6 中文分词、分页查询、高亮显示等
2012-12-09 23:35 18341、准备工作 下载lucene 3.6.1 : htt ... -
Maven实战(九)——打包的技巧(转)
2012-10-12 00:41 944“打包“这个词听起 ... -
基于Maven的web工程如何配置嵌入式Jetty Server开发调试环境(转)
2012-10-12 00:28 9501、首先在web工程的POM文件里添加依赖jar包如下: ... -
轻轻松松学Solr(1)--概述及安装[转]
2012-09-18 14:59 1000概述 这段时间对企 ... -
分析Netty工作流程[转]
2012-09-04 19:02 897下面以Netty中Echo的例 ... -
让eclipse在ubuntu下面好看一点
2012-03-27 10:17 932<p> </p> <h1 cla ... -
zookeeper安装和应用场合(名字,配置,锁,队列,集群管理)[转]
2012-01-12 17:59 1657安装和配置详解 本文 ... -
Jakarta-Common-BeanUtils使用笔记[转]
2012-01-10 14:13 1163Jakarta-Common-BeanUtils ... -
一个关于Java Thread wait(),notify()的实用例【转】
2012-01-07 16:05 1027///// // ProducerConsume ... -
Java基础:Java中的 assert 关键字解析【转】
2012-01-06 19:50 1072J2SE 1.4在语言上提供了 ... -
一篇不错的讲解Java异常的文章(转载)----感觉很不错,读了以后很有启发[转]
2012-01-06 15:02 1277六种异常处理的陋习 ... -
如何解决HP QC(Quality Center)在Windows 7下不能工作的问题
2011-12-26 10:48 1594HP QC(Quantity Center) 是一款不错的测 ... -
JAVA读写文件,中文乱码 【转】
2011-12-19 23:43 2128最近在做HTML静态生成,需要从硬盘上把模版文件的内容读出来。 ... -
Java 6 JVM参数选项大全(中文版)【转】
2011-12-19 19:51 979Java 6 JVM参数选项大全(中文版) 作者 ... -
使用assembly plugin实现自定义打包【转】
2011-12-13 01:58 979在上一篇文章中,讨论到在对maven的机制不熟悉的情况下,为了 ... -
使用maven ant task实现非标准打包[转]
2011-12-13 01:56 1053maven很强大,但是总有些事情干起来不是得心应手,没有使用a ... -
Java日期转换SimpleDateFormat格式大全【转】
2011-12-08 20:22 132324小时制时间 显示: public clas ... -
使用Spring的表单标签库
2011-11-22 20:08 108313.9. 使用Spring的 ...
相关推荐
.NET Standard 2.1、.NET 6、.NET 7、.NET8 版本SQLBuilder,Expression表达式转换为SQL语句,支持SqlServer、MySql、Oracle、Sqlite、PostgreSql;基于Dapper实现了不同数据库对应的数据仓储Repository;
各国数字服务贸易进出口额(2010-2022年)
2024版银行及保险高净值客户健康绿皮书
【博客】MVC、MVP、MVVM设计模式的案例_pgc
Python数据抓取淘宝电商商品图片
基于python开发爬虫脚本,并使用django,echarts对数据进行分析_pgc
Tesseract繁体中文OCR数据文件,垂直布局
## 介绍 碳排放数据是衡量地方经济发展与环境可持续性的重要指标。碳排放数据通常包括二氧化碳排放量,来源包括能源消耗以及工业、交通、建筑等领域的排放。由于中国地理辽阔、经济发展不平衡,各地的碳排放水平差异较大。本次分享的数据是根据EDGAR资源提取的中国地级市二氧化碳排放数据,数据年份为2000-2023年 ## 一、数据介绍 数据名称:中国地级市二氧化碳排放数据 数据年份:2000-2023年 数据范围:300个地级以上城市 数据来源:EDGAR_2024_GHG of October 2024 数据说明:根据EDGAR提取的城市碳排放数据 ## 二、数据指标 年份、省份、城市、城市代码、所属地域、二氧化碳排放总量
基于多算法融合的齿轮箱故障诊断模型优化:GADF-CNN-BKA-LSSVM算法的原理与应用,基于GADF-CNN-BKA-LSSVM的齿轮箱故障诊断 首先,利用格拉姆角场差(GADF)时频分辨率高、可以深度反映时间序列内在结构和关系的特点,对采集到的一维故障数据信号转为二维图像,得到图像后并将图像进行降维处理;然后,将第一步得到的格拉姆角场差图像输入二维卷积神经网络(CNN)进行自适应故障特征提取;最后,取CNN的全连接层结果作为LSSVM分类器的输入,并采用黑翅鸢优化算法BKA对LSSVM分类器的超参数进行优化,以提高模型泛化能力,避免模型陷入局部最优 附赠常春藤优化算法IVY和鹈鹕优化算法POA ,基于GADF-CNN-BKA-LSSVM; 故障诊断; 图像降维; 特征提取; 模型泛化; 常春藤优化算法IVY; 鹈鹕优化算法POA,基于多算法优化的齿轮箱故障诊断:GADF-CNN-BKA-LSSVM模型
省级-创新资源错配指数(2000-2022年)
TencentMeeting_0300000000_3.30.30.420_x86_64.publish.officialwebsite.exe
基于FPGA的Endat绝对值编码器PG卡源代码优化与实现:海德汉1313编码器应用案例,基于fpga的海德汉1313 Endat绝对值编码器pg卡源代码 ,基于FPGA的海德汉1313; Endat; 绝对值编码器; PG卡; 源代码,基于FPGA的Endat绝对值编码器PG卡源代码
【Vue+PHP】基于thinkphp6、vue(iview-admin)前后端分离快速开发框架
## 1.基本信息 数据名称:ALOS 12.5m DEM 数据 空间位置:中国 数据格式:栅格 数据大小:61.5GB 空间分辨率:12.5m ## 2.内容概述 ALOS 12.5m DEM 数据,是ALOS(Advanced Land Observing Satellite. 2006年发射)卫星相控阵型L波段合成孔径雷达(PALSAR)采集的高程数据。PALSAR传感器具有高分辨率、扫描式合成孔径雷达、极化三种观测模式。ALOS Dem高程数据水平及垂直精度可达12.5米。 ALOS是日本宇宙航空研究所(JAXA)的Advanced Land Observing Satellite-1(高级陆地观测卫星-1,ALOS)项目。ALOS卫星载有三个传感器:全色遥感立体测绘仪(PRISM),主要用于数字高程测绘;先进可见光与近红外辐射计-2(AVNIR-2),用于精确陆地观测;相控阵型L波段合成孔径雷达(PALSAR),用于全天时全天候陆地观测。
基于六自由度机械臂模型的MPC预测控制方法研究,六自由度机械臂模型预测控制mpc ,六自由度机械臂;模型预测控制;MPC,六自由度机械臂的MPC预测控制模型
## 介绍 碳排放数据是衡量地方经济发展与环境可持续性的重要指标。碳排放数据通常包括二氧化碳排放量,来源包括能源消耗以及工业、交通、建筑等领域的排放。由于中国地理辽阔、经济发展不平衡,各地的碳排放水平差异较大。 本次分享的数据是根据EDGAR资源提取的中国各省、地级市、区县二氧化碳排放数据,数据年份为1980-2023年。 ## 一、数据介绍 数据名称:中国省、市、县二氧化碳排放数据 数据年份:1980-2023年 数据范围:各省、地级市、区县 数据来源:EDGAR_2024_GHG of October 2024 数据说明:根据EDGAR提取的城市碳排放数据 ## 二、数据指标 年份、省份、城市、城市代码、区县、二氧化碳排放总量 ## 三、数据展示
基于混合整数规划与次梯度法的分散PEV充电控制策略:比较与验证分析,基于混合整数规划问题次梯度法的分散PEV控制 本文提出了一种解决智能电网中充电式电动汽车(pev)车队充电问题的分散方法,其中通过MPC策略将全局和局部约束和目标与电网模型一起考虑。 充电问题的表示涉及连续变量和整数变量的组合(特别是布尔性质的)。 它被公式化为混合整数线性规划(MILP)问题,使用次梯度方法求解。 将所提出的方法与集中式方法进行比较,集中式方法通常通过分支定界算法来解决。 结果表明,分散式方法能够实现接近集中式方法的性能,同时减少计算负担,特别是对于大型车队。 这些发现通过在测试案例上执行的模拟来支持。 ,混合整数规划问题;次梯度法;分散PEV控制;MPC策略;全局和局部约束;MILP问题;计算负担;测试案例模拟,基于混合整数规划的次梯度法:分散PEV充电控制策略研究
.archivetemp活动七:小古文.doc
适用操作系统:windows。 适用CPU架构:x64。
数值分析与公式定理