- 浏览: 109040 次
- 性别:
- 来自: 北京
最新评论
-
nwpu7:
解决问题,感谢感谢
org.hibernate.hql.ast.HqlToken 错误weblogic异常 -
zhangna307:
如果已经有对应的hibernte-cfg.xml文件,还是报这 ...
Could not instantiate cache implementation异常处理 -
zzw118:
不错,解决了我的问题!
Could not instantiate cache implementation异常处理 -
flank.tai:
女孩的技术都这么牛!!顶。不过图片看不了呀!!!
深度技术 USB启动维护盘制作工具 -
supercode:
dell的服务器与自己diy的相同配置,价格高出多少左右
Dell PowerEdge 2800 服务器 Windows 2003安装手册
Aspect Oriented Programming
AOP概念
Aspect Oriented Programming(AOP)是近来较为热门的一个话题。AOP,国内
大致译作“面向方面编程”。
“面向方面编程”,这样的名字并不是非常容易理解,且容易产生一些误导。笔者不止
一次听到类似“OOP/OOD11即将落伍,AOP是新一代软件开发方式”这样的发言。显然,
发言者并没有理解AOP的含义。
Aspect,没错,的确是“方面”的意思。不过,华语传统语义中的“方面”,大多数情
况下指的是一件事情的不同维度、或者说不同角度上的特性,比如我们常说:“这件事情要
从几个方面来看待”,往往意思是:需要从不同的角度来看待同一个事物。这里的“方面”,
指的是事务的外在特性在不同观察角度下的体现。
而在AOP中,Aspect的含义,可能更多的理解为“切面”比较合适。所以笔者更倾向
于“面向切面编程”的译法。
另外需要提及的是,AOP、OOP在字面上虽然非常类似,但却是面向不同领域的两种
设计思想。OOP(面向对象编程)针对业务处理过程的实体及其属性和行为进行抽象封装,
以获得更加清晰高效的逻辑单元划分。
而AOP则是针对业务处理过程中的切面进行提取,它所面对的是处理过程中的某个步
骤或阶段,以获得逻辑过程中各部分之间低耦合性的隔离效果。这两种设计思想在目标上有
着本质的差异。
上面的陈述可能过于理论化,举个简单的例子,对于“雇员”这样一个业务实体进行封
装,自然是OOP/OOD的任务,我们可以为其建立一个“Employee”类,并将“雇员”相
关的属性和行为封装其中。而用AOP设计思想对“雇员”进行封装将无从谈起。
同样,对于“权限检查”这一动作片断进行划分,则是AOP的目标领域。而通过OOD/OOP
对一个动作进行封装,则有点不伦不类。
换而言之,OOD/OOP面向名词领域,AOP面向动词领域。
AOP和OOD/OOP并不冲突,我们完全可以在一个应用系统中同时应用OOD/OOP和
AOP设计思想,通过OOD/OOP对系统中的业务对象进行建模,同时通过AOP对实体处理
过程中的阶段进行隔离处理。即使不是OOD/OOP,而是在传统的POP(面向过程编程)中,
AOP也能起到同样的作用。
将不同阶段领域加以分隔,这是否就算是AOP呢?
AOP还有另外一个重要特点:源码组成无关性。
11 OOD = Object Oriented Design OOP = Object Oriented Programming
SpringFrameWork Developer’s Guide Version 0.6
October 8, 2004 So many open source projects. Why not Open your Documents?
倘若应用中通过某个具体的业务逻辑类实现了独立的权限检查,而请求调度方法通过预
编码调用这个权限模块实现权限管理。那么这也不算是AOP。对于AOP组件而言,很重要
的一点就是源码组成无关性,所谓源码组成无关性,体现在具体设计中就是AOP组件必须
与应用代码无关,简单来讲,就是应用代码可以脱离AOP组件独立编译。
为了实现源码组成无关性,AOP往往通过预编译方式(如AspectJ)和运行期动态代理
模式(如Spring AOP 和JBoss AOP)实现。
稍后章节中我们会就Spring Framework中的AOP实现机制进行更加深入的探讨。
下面先来看AOP中几个比较重要的概念:
1. 切面(Aspect)
切面,对象操作过程中的截面。这可能是AOP中最关键的一个术语。
我们首先来看一个应用开发中常见的切面:用户权限检查。大概只要是完整的应用,都
少不了用户权限检查这个模块,不同身份的用户可以做什么,不可以做什么,均由这个模块
加以判定。而这个模块调用的位置通常也比较固定:用户发起请求之后,执行业务逻辑之前。
针对权限检查这一模块进行分离,我们就得到了一个切面:
切面意义何在?
首先根据上例,假设我们实现了一个通用的权限检查模块,那么就可以在这层切面上进
行统一的集中式权限管理。而业务逻辑组件则无需关心权限方面的问题。也就是说,通过切
面,我们可以将系统中各个不同层次上的问题隔离开来,实现统一集约式处理。各切面只需
集中于自己领域内的逻辑实现。
这一方面使得开发逻辑更加清晰,专业化分工更加易于进行;另一方面,由于切面的隔
离,降低了耦合性,我们就可以在不同的应用中将各个切面组合使用,从而使得代码可重用
性大大增强。
SpringFrameWork Developer’s Guide Version 0.6
October 8, 2004 So many open source projects. Why not Open your Documents?
2. 连接点(JoinPoint)
程序运行过程中的某个阶段点。如某个方法调用,或者某个异常被抛出。
3. 处理逻辑(Advice)
在某个连接点所采用的处理逻辑
(这里的Advice,国内不少文案中翻译为“通知”,估计是源于金山词霸,与实际含义不符,因而这
里采用意译)
处理逻辑的调用模式通常有三种:
i. Around
在连接点前后插入预处理过程和后处理过程。
ii. Before
仅在连接点之前插入预处理过程。
iii. Throw
在连接点抛出异常时进行异常处理。
4. 切点(PointCut)
一系列连接点的集合,它指明处理方式(Advice)将在何时被触发。
上述几个概念我们将在稍后的“AOP应用”一节中结合实际使用进行具体探讨。
SpringFrameWork Developer’s Guide Version 0.6
October 8, 2004 So many open source projects. Why not Open your Documents?
AOP in Spring
Spring中提供的内置AOP支持,是基于动态AOP机制实现。从技术角度来讲,所谓动
态AOP,即通过动态Proxy模式,在目标对象的方法调用前后插入相应的处理代码。
而Spring AOP中的动态Proxy模式,则是基于Java Dynamic Proxy(面向Interface)
和CGLib(面向Class)实现。
前面曾经提及,Spring Framework中的“事务管理”服务,实际上是借助AOP机制
完成。我们这里就以“事务管理”为例,对动态AOP的实现加以探讨,一方面对动态AOP
的实现原理加以探究,另一方面,也可以加深对Spring中事务管理机制的理解。
首先,我们来看基于Java Dynamic Proxy的AOP实现原理。
Dynamic Proxy 与Spring AOP
Dynamic Proxy是JDK 1.3版本中新引入的一种动态代理机制。它是Proxy模式的一
种动态实现版本。
我们先来看传统方式下一个Proxy的实现实例。
假设我们有一个UserDAO接口及其实现类UserDAOImp:
UserDAO.java:
public interface UserDAO {
public void saveUser(User user);
}
UserDAOImp.java:
public class UserDAOImp implements UserDAO{
public void saveUser(User user) {
……
}
}
UserDAOImp.saveUser方法中实现了针对User对象的数据库持久逻辑。
如果我们希望在UserDAOImp.saveUser方法执行前后追加一些处理过程,如启动/
提交事务,而不影响外部代码的调用逻辑,那么,增加一个Proxy类是个不错的选择:
UserDAOProxy.java
public class UserDAOProxy implements UserDAO {
private UserDAO userDAO;
public UserDAOProxy(UserDAO userDAO) {
SpringFrameWork Developer’s Guide Version 0.6
October 8, 2004 So many open source projects. Why not Open your Documents?
this.userDAO = userDAO;
}
public void saveUser(User user) {
UserTransaction tx = null;
try {
tx = (UserTransaction) (
new InitialContext().lookup("java/tx")
);
userDAO.saveUser(user);
tx.commit();
} catch (Exception ex) {
if (null!=tx){
try {
tx.rollback();
}catch(Exception e) {
}
}
}
}
}
UserDAOProxy同样是UserDAO接口的实现,对于调用者而言,saveUser方法的使
用完全相同,不同的是内部实现机制已经发生了一些变化――我们在UserDAOProxy中为
UserDAO.saveUser方法套上了一个JTA事务管理的外壳。
上面是静态Proxy模式的一个典型实现。
现在假设系统中有20个类似的接口,针对每个接口实现一个Proxy,实在是个繁琐无
味的苦力工程。
Dynamic Proxy的出现,为这个问题提供了一个更加聪明的解决方案。
我们来看看怎样通过Dynamic Proxy解决上面的问题:
public class TxHandler implements InvocationHandler {
private Object originalObject;
public Object bind(Object obj) {
this.originalObject = obj;
return Proxy.newProxyInstance(
obj.getClass().getClassLoader(),
obj.getClass().getInterfaces(),
SpringFrameWork Developer’s Guide Version 0.6
October 8, 2004 So many open source projects. Why not Open your Documents?
this);
}
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
Object result = null;
if (!method.getName().startsWith("save")) {
UserTransaction tx = null;
try {
tx = (UserTransaction) (
new InitialContext().lookup("java/tx")
);
result = method.invoke(originalObject, args);
tx.commit();
} catch (Exception ex) {
if (null != tx) {
try {
tx.rollback();
} catch (Exception e) {
}
}
}
} else {
result = method.invoke(originalObject, args);
}
return result;
}
}
首先注意到,上面这段代码中,并没有出现与具体应用层相关的接口或者类引用。也就
是说,这个代理类适用于所有接口的实现。
其中的关键在两个部分:
1.
return Proxy.newProxyInstance(
obj.getClass().getClassLoader(),
obj.getClass().getInterfaces(),
SpringFrameWork Developer’s Guide Version 0.6
October 8, 2004 So many open source projects. Why not Open your Documents?
this);
java.lang.reflect.Proxy.newProxyInstance方法根据传入的接口类型
(obj.getClass().getInterfaces())动态构造一个代理类实例返回,这个代理类是JVM
在内存中动态构造的动态类,它实现了传入的接口列表中所包含的所有接口。
这里也可以看出,Dynamic Proxy要求所代理的类必须是某个接口的实现
(obj.getClass().getInterfaces()不可为空),否则无法为其构造响应的动态类。这也
就是为什么Spring对接口实现类通过Dynamic Proxy实现AOP,而对于没有实现任何接口
的类通过CGLIB实现AOP机制的原因,关于CGLIB,请参见稍后章节的讨论。
2.
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
……
result = method.invoke(originalObject, args);
……
return result;
}
InvocationHandler.invoke方法将在被代理类的方法被调用之前触发。通过这个方
法中,我们可以在被代理类方法调用的前后进行一些处理,如代码中所示,
InvocationHandler.invoke方法的参数中传递了当前被调用的方法(Method),以及被
调用方法的参数。
同时,我们可以通过Method.invoke方法调用被代理类的原始方法实现。这样,我们
就可以在被代理类的方法调用前后大做文章。
在示例代码中,我们为所有名称以“save”开头的方法追加了JTA事务管理。
谈到这里,可以回忆一下Spring事务配置中的内容:
<property name="transactionAttributes">
<props>
<prop key="save*">PROPAGATION_REQUIRED</prop>
<prop key="get*">PROPAGATION_REQUIRED,readOnly</prop>
</props>
</property>
想必大家已经猜测到Spring事务管理机制的实现原理。
是的,只需通过一个Dynamic Proxy对所有需要事务管理的Bean进行加载,并根据配
置,在invoke方法中对当前调用的方法名进行判定,并为其加上合适的事务管理代码,那
么就实现了Spring式的事务管理。
当然,Spring中的AOP实现更为复杂和灵活,不过基本原理一致。
SpringFrameWork Developer’s Guide Version 0.6
October 8, 2004 So many open source projects. Why not Open your Documents?
代码胜千言,下面是笔者在客户培训过程中编写的一个Dynamic Proxy based AOP
实现示例,非常简单,有兴趣的读者可以看看。
AOPHandler.java:
public class AOPHandler implements InvocationHandler {
private static Log logger = LogFactory.getLog(AOPHandler.class);
private List interceptors = null;
private Object originalObject;
/**
* 返回动态代理实例
* @param obj
* @return
*/
public Object bind(Object obj) {
this.originalObject = obj;
return Proxy.newProxyInstance(obj.getClass().getClassLoader(),
obj
.getClass().getInterfaces(), this);
}
/**
* 在Invoke方法中,加载对应的Interceptor,并进行
* 预处理(before)、后处理(after)以及异常处理(exceptionThrow)过程
*/
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
Object result = null;
Throwable ex = null;
InvocationInfo invInfo = new InvocationInfo(proxy, method, args,
result, ex);
logger.debug("Invoking Before Intercetpors!");
invokeInterceptorsBefore(invInfo);
SpringFrameWork Developer’s Guide Version 0.6
October 8, 2004 So many open source projects. Why not Open your Documents?
try {
logger.debug("Invoking Proxy Method!");
result = method.invoke(originalObject, args);
invInfo.setResult(result);
logger.debug("Invoking After Method!");
invokeInterceptorsAfter(invInfo);
} catch (Throwable tr) {
invInfo.setException(tr);
logger.debug("Invoking exceptionThrow Method!");
invokeInterceptorsExceptionThrow(invInfo);
throw new AOPRuntimeException(tr);
}
return result;
}
/**
* 加载Interceptor
* @return
*/
private synchronized List getIntercetors() {
if (null == interceptors) {
interceptors = new ArrayList();
//Todo:读取配置,加载Interceptor实例
//interceptors.add(new MyInterceptor());
}
return interceptors;
}
/**
* 执行预处理方法
* @param invInfo
*/
private void invokeInterceptorsBefore(InvocationInfo invInfo) {
List interceptors = getIntercetors();
int len = interceptors.size();
SpringFrameWork Developer’s Guide Version 0.6
October 8, 2004 So many open source projects. Why not Open your Documents?
for (int i = 0; i < len; i++) {
((Interceptor) interceptors.get(i)).before(invInfo);
}
}
/**
* 执行后处理方法
* @param invInfo
*/
private void invokeInterceptorsAfter(InvocationInfo invInfo) {
List interceptors = getIntercetors();
int len = interceptors.size();
for (int i = len - 1; i >= 0; i--) {
((Interceptor) interceptors.get(i)).after(invInfo);
}
}
/**
* 执行异常处理方法
* @param invInfo
*/
private void invokeInterceptorsExceptionThrow(InvocationInfo
invInfo) {
List interceptors = getIntercetors();
int len = interceptors.size();
for (int i = len - 1; i >= 0; i--) {
((Interceptor)
interceptors.get(i)).exceptionThrow(invInfo);
}
}
}
Interceptor.java:
public interface Interceptor {
public void before(InvocationInfo invInfo);
public void after(InvocationInfo invInfo);
public void exceptionThrow(InvocationInfo invInfo);
}
InvocationInfo.java:
SpringFrameWork Developer’s Guide Version 0.6
October 8, 2004 So many open source projects. Why not Open your Documents?
public class InvocationInfo {
Object proxy;
Method method;
Object[] args;
Object result;
Throwable Exception;
public InvocationInfo(Object proxy, Method method, Object[] args,
Object result, Throwable exception) {
super();
this.proxy = proxy;
this.method = method;
this.args = args;
this.result = result;
Exception = exception;
}
public Object getResult() {
return result;
}
public void setResult(Object result) {
this.result = result;
}
public Object[] getArgs() {
return args;
}
public void setArgs(Object[] args) {
this.args = args;
}
public Throwable getException() {
return Exception;
}
public void setException(Throwable exception) {
Exception = exception;
}
public Method getMethod() {
return method;
}
public void setMethod(Method method) {
this.method = method;
}
public Object getProxy() {
return proxy;
}
SpringFrameWork Developer’s Guide Version 0.6
October 8, 2004 So many open source projects. Why not Open your Documents?
public void setProxy(Object proxy) {
this.proxy = proxy;
}
}
AOPFactory.java:
public class AOPFactory {
private static Log logger = LogFactory.getLog(AOPFactory.class);
/**
* 根据类名创建类实例
* @param clzName
* @return
* @throws ClassNotFoundException
*/
public static Object getClassInstance(String clzName){
Class cls;
try {
cls = Class.forName(clzName);
return (Object)cls.newInstance();
} catch (ClassNotFoundException e) {
logger.debug(e);
throw new AOPRuntimeException(e);
} catch (InstantiationException e) {
logger.debug(e);
throw new AOPRuntimeException(e);
} catch (IllegalAccessException e) {
logger.debug(e);
throw new AOPRuntimeException(e);
}
}
/**
* 根据传入的类名,返回AOP代理对象
* @param clzName
* @return
*/
public static Object getAOPProxyedObject(String clzName){
SpringFrameWork Developer’s Guide Version 0.6
October 8, 2004 So many open source projects. Why not Open your Documents?
AOPHandler txHandler = new AOPHandler();
Object obj = getClassInstance(clzName);
return txHandler.bind(obj);
}
}
MyInterceptor.java:
public class MyInterceptor implements Interceptor{
private static Log logger = LogFactory.getLog(MyInterceptor.class);
public void before(InvocationInfo invInfo) {
logger.debug("Pre-processing");
}
public void after(InvocationInfo invInfo) {
logger.debug("Post-processing");
}
public void exceptionThrow(InvocationInfo invInfo) {
logger.debug("Exception-processing");
}
}
Spring中Dynamic Proxy AOP实现类为:
org.springframework.aop.framework.JdkDynamicAopProxy
SpringFrameWork Developer’s Guide Version 0.6
October 8, 2004 So many open source projects. Why not Open your Documents?
CGLib 与Spring AOP
上面曾经提过,Dynamic Proxy是面向接口的动态代理实现,其代理对象必须是某个
接口的实现。Dynamic Proxy通过在运行期构建一个此接口的动态实现类完成对目标对象
的代理(相当于在运行期动态构造一个UserDAOProxy,完成对UserDAOImp的代理任
务)。
而如果目标代理对象并未实现任何接口,那么Dynamic Proxy就失去了创建动态代理
类的基础依据。此时我们需要借助一些其他的机制实现动态代理机制。
Spring中,引入了CGLib作为无接口情况下的动态代理实现。
CGLib与Dynamic Proxy的代理机制基本类似,只是其动态生成的代理对象并非某个
接口的实现,而是针对目标类扩展的子类。
换句话说,Dynamic Proxy返回的动态代理类,是目标类所实现的接口的另一个实现
版本,它实现了对目标类的代理(如同UserDAOProxy与UserDAOImp的关系)。而CGLib
返回的动态代理类,则是目标代理类的一个子类(代理类扩展了UserDAOImp类)。
与Dynamic Proxy中的Proxy和InvocationHandler相对应,Enhancer和
MethodInterceptor在CGLib中负责完成代理对象创建和方法截获处理。
下面是通过CGLib进行动态代理的示例代码:
AOPInstrumenter.java:
public class AOPInstrumenter implements MethodInterceptor {
private static Log logger =
LogFactory.getLog(AOPInstrumenter.class);
private Enhancer enhancer = new Enhancer();
public Object getInstrumentedClass(Class clz) {
enhancer.setSuperclass(clz);
enhancer.setCallback(this);
return enhancer.create();
}
SpringFrameWork Developer’s Guide Version 0.6
October 8, 2004 So many open source projects. Why not Open your Documents?
public Object intercept(
Object o,
Method method,
Object[] methodParameters,
MethodProxy methodProxy)
throws Throwable {
logger.debug("Before Method =>"+method.getName());
Object result = methodProxy.invokeSuper(o, methodParameters);
logger.debug("After Method =>"+method.getName());
return result;
}
}
测试代码:
AOPInstrumenter aopInst = new AOPInstrumenter();
UserDAOImp userDAO =
(UserDAOImp) aopInst.getInstrumentedClass(UserDAOImp.class);
User user = new User();
user.setName("Erica");
userDAO.saveUser(user);
有兴趣的读者可以利用CGLib对Dynamic Proxy中给出的AOP实现代码进行改造。
Spring中,基于CGLib的AOP实现位于:
org.springframework.aop.framework.Cglib2AopProxy
SpringFrameWork Developer’s Guide Version 0.6
October 8, 2004 So many open source projects. Why not Open your Documents?
AOP 应用
前面介绍AOP概念的章节中,曾经以权限检查为例说明AOP切面的概念。
权限检查的确是AOP应用中一个热门话题,假设如果现在出现了一个设计完备的权限
管理组件,那么将是一件多么惬意的事情,我们只需要在系统中配置一个AOP组件,即可
完成以往需要大费周张才能完成的权限判定功能。
可惜目前还没有这样一个很完善的实现。一方面权限检查过于复杂多变,不同的业务系
统中的权限判定逻辑可能多种多样(如对于某些关键系统而言,很可能出现需要同时输入两
个人的密码才能访问的需求)。另一方面,就目前的AOP应用粒度而言,“权限管理”作为
一个切面尚显得过于庞大,需要进一步切分设计,设计复杂,实现难度较大。
目前最为实用的AOP应用,可能就是Spring中基于AOP实现的事务管理机制,也正是
这一点,使得Spring AOP大放异彩。
之前的内容中,我们大多围绕Spring AOP的实现原理进行探讨,这里我们围绕一个简
单的AOP Interceptor实例,看看Spring中AOP机制的应用与开发。
在应用系统开发过程中,我们通常需要对系统的运行性能有所把握,特别是对于关键业
务逻辑的执行效能,而对于执行效能中的执行时间,则可能是重中之重。
我们这里的实例的实现目标,就是打印出目标Bean中方法的执行时间。
首先,围绕开篇中提到的几个重要概念,我们来看看Spring中对应的实现。
1. 切点(PointCut)
一系列连接点的集合,它指明处理方式(Advice)将在何时被触发。
对于我们引用开发而言,“何时触发”的条件大多是面向Bean的方法进行制定。实
际上,只要我们在开发中用到了Spring的配置化事务管理,那么就已经进行了PointCut
设置,我们可以指定对所有save开头的方法进行基于AOP的事务管理:
<property name="transactionAttributes">
<props>
<prop key="save*">PROPAGATION_REQUIRED</prop>
</props>
</property>
同样,对于我们的AOP组件而言,我们也可以以方法名作为触发判定条件。
我们可以通过以下节点,为我们的组件设定触发条件。
<bean id="myPointcutAdvisor"
class="org.springframework.aop.support.RegexpMethodPointcutAdv
isor">
<property name="advice">
<ref local="MyInterceptor" />
</property>
<property name="patterns">
SpringFrameWork Developer’s Guide Version 0.6
October 8, 2004 So many open source projects. Why not Open your Documents?
<list>
<value>.*do.*</value>
<value>.*execute.*</value>
</list>
</property>
</bean>
RegexpMethodPointcutAdvisor是Spring中提供的,通过逻辑表达式指定方法
判定条件的支持类。其中的逻辑表达式解析采用了Apache ORO组件实现,关于逻
辑表达式的语法请参见Apache ORO文档。
上面我们针对MyInterceptor设定了一个基于方法名的触发条件,也就是说,当
目标类的指定方法运行时,MyInterceptor即被触发。
MyInterceptor是我们对应的AOP逻辑处理单元,也就是所谓的Advice。
2. Advice
Spring中提供了以下几种Advice:
1. Interception around advice
Spring中最基本的Advice类型,提供了针对PointCut的预处理、后处理过程
支持。
我们将使用Interception around advice完成这里的实例。
2. Before advice
仅面向了PointCut的预处理。
3. Throws advice
仅面向PointCut的后处理过程中的异常处理。
4. After Returning advice
仅面向PointCut返回后的后处理过程。
5. Introduction advice
Spring中较为特殊的一种Advice,仅面向Class层面(而不像上述Advice面
向方法层面)。通过Introduction advice我们可以实现多线程访问中的类锁
定。
Spring中采用了AOP联盟(AOP Alliance)12的通用AOP接口(接口定义位于
aopalliance.jar)。这里我们采用aopalliance.jar中定义的MethodInterceptor作为
我们的Advice实现接口:
public class MethodTimeCostInterceptor implements
MethodInterceptor,
Serializable {
protected static final Log logger = LogFactory
12 http://aopalliance.sourceforge.net/
SpringFrameWork Developer’s Guide Version 0.6
October 8, 2004 So many open source projects. Why not Open your Documents?
.getLog(MethodTimeCostInterceptor.class);
public Object invoke(MethodInvocation invocation) throws
Throwable {
long time = System.currentTimeMillis();
Object rval = invocation.proceed();
time = System.currentTimeMillis() - time;
logger.info("Method Cost Time => " + time + " ms");
return rval;
}
}
对应配置如下:
<bean id="MyInterceptor"
class="net.xiaxin.interceptors.MethodTimeCostInterceptor"
/>
除此之外,我们还需要定义一个Spring AOP ProxyFactory用以加载执行AOP组件。
定义如下:
<bean id="myAOPProxy"
class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="proxyInterfaces">
<value>net.xiaxin.ITest</value>
</property>
<!—是否强制使用CGLIB进行动态代理
<property name="proxyTargetClass">
<value>true</value>
</property>
-->
<property name="target">
<ref local="test" />
</property>
<property name="interceptorNames">
<value>myPointcutAdvisor</value>
</property>
SpringFrameWork Developer’s Guide Version 0.6
October 8, 2004 So many open source projects. Why not Open your Documents?
</bean>
<bean id="test" class="net.xiaxin.Test"/>
其中的test是我们用于测试的一个类,它实现了ITest接口。
public interface ITest {
public abstract void doTest();
public abstract void executeTest();
}
public class Test implements ITest {
public void doTest(){
for (int i=0;i<10000;i++){}
}
public void executeTest(){
for (int i=0;i<25000;i++){}
}
}
通过以上工作,我们的MyInterceptor即被加载,并将在Test.doTest和
Test.executeTest方法调用时被触发,打印出这两个方法的执行时间。
public void testAOP() {
ApplicationContext ctx=new
FileSystemXmlApplicationContext("bean.xml");
ITest test = (ITest) ctx.getBean("myAOPProxy");
test.doTest();
test.executeTest();
}
发表评论
-
求100以内的质数
2011-01-11 12:42 941题目:除了能被自身和1整除外,不能被其他数整除的数,为素数 ... -
整理开始
2010-03-15 16:49 791将近半年没来javaeye了,自己的知识没能及时梳理。从今天开 ... -
dddd
2009-09-16 17:11 815ddddddddd -
java文件上传下载
2009-09-16 17:07 5528文件上传在web应用中非常普遍,要在jsp环境中实现文件上传功 ... -
实现Ext表单对checkBoxGroup的统一管理
2009-08-11 13:21 13731 对于类型是checkboxgroup的数据,数据库中保存数 ... -
cvsnt 配置
2009-06-03 15:51 1107CvsNT设置1.安装CvsNT,并 ... -
发生算术溢出或其它算术异常。
2009-05-26 17:16 3724今天报了一个bug,sql在DB2执行的时候报“发生算术溢出或 ... -
回车代替点按钮提交
2009-05-22 16:46 1517输入框+按钮 完成的操作和 输入框+回车 完成一样的操作 & ... -
eclipse下修改代码重启tomcat的问题
2009-05-04 17:40 2277忍受了很久的eclipse下修改代码重启tomcat的问题,今 ... -
urlrewritefilter 例子
2009-04-17 17:31 1157我在tomcat下跑通了一个例子,关于urlRewritefi ... -
正则表达式
2009-03-20 17:35 846如果你曾经用过Perl或任何其他内建正则表达式支持的语言 ... -
正则表达式大全
2009-03-20 16:35 898常用正则表达式大全! ... -
Could not instantiate cache implementation异常处理
2009-03-06 14:34 8021今天遇到了一个很奇怪的问题 我照例增加了一套新功能,但一切就 ... -
整理分页
2009-02-24 16:28 873从今天开始打算整理一下分页、上传下载、程序里调用存储 ... -
Dell PowerEdge 2800 服务器 Windows 2003安装手册
2009-02-06 15:40 2250Dell PowerEdge 2800 服务器 W ... -
新年第一天的工作
2009-02-05 11:50 754初十一来上班了,工作安排是解决河北bug,但是公司服务器dow ... -
深度技术 USB启动维护盘制作工具
2009-02-05 11:27 5932前言 大容量的移动硬盘和U盘已经越来越普及,很多朋友希望将 ... -
Tomcat:IOException while loading persisted session
2009-01-05 10:20 881错误描述:....while loading persiste ... -
display tag
2008-12-29 10:19 4319DisplayTag Tutorial by DarrenWa ... -
eclipse快捷键大全
2008-12-17 17:11 614Ctrl+1 快速修复(最经典的快捷键,就不用多说了)Ctrl ...
相关推荐
总结起来,Spring AOP注解版通过简单易懂的注解,使得面向切面编程变得更加直观和方便。它降低了横切关注点与业务逻辑之间的耦合度,提高了代码的可维护性和复用性。通过合理利用这些注解,开发者可以轻松地实现日志...
在Spring Boot应用中,Spring AOP(面向切面编程)是一种强大的工具,它允许我们创建横切关注点,如日志记录、权限检查等,这些关注点可以被编织到应用程序的多个点上,而无需侵入核心业务逻辑。在本案例中,我们将...
首先,我们来看注解在Spring AOP中的应用。在传统的AOP配置中,我们需要定义切入点表达式和通知(advice)在XML配置文件中。然而,使用注解可以让这些配置变得更加直观和易于维护。例如,我们可以使用`@Aspect`注解...
membercache已经有基于spring的aop包,并且这个包是谷歌提供的开源代码,里面代码我看了写的很不错的哈。 最近项目中需要用的redis,记得之前操作redis 的代码和自己订单业务混合在一起。维护是个问题,阅读也不...
在Spring框架中,AOP(面向切面编程)是一种强大的设计模式,它允许开发者将关注点从业务...通过实际操作,你会发现Spring AOP使得编写和管理切面变得非常简单,同时让代码更加整洁,遵循了面向切面编程的设计原则。
常见的情况是,我们到处去看哪里有长得漂亮身材又好的mm,然后打听她们的兴趣爱好、qq号、电话号、ip号、iq号………,想办法认识她们,投其所好送其所要,然后嘿嘿……这个过程是复杂深奥的,我们必须自己设计和面对...
在Spring Boot中,AOP的集成使得这些常见任务的实现变得更加简单和高效。 首先,我们要理解什么是AOP。AOP是一种编程范式,旨在减少代码冗余,通过将关注点分离为不同的“切面”来提高代码的可维护性和复用性。这些...
"学习spring必看ppt,总结的很全面"这个标题暗示了这是一个全面涵盖Spring核心概念和应用的教程资料,包括了Spring框架的关键组成部分。 1. **Spring 概述**:Spring是一个开源的Java平台,它简化了企业级应用的...
从给定文件信息的内容来看,本文将会涉及到Spring中的几个关键概念,包括IoC、DI(依赖注入)、Spring Web项目、Spring AOP、以及Spring JDBC和事务管理。 1. **Spring简介** 1.1 **IOC和DI** IoC(控制反转)是一...
首先,我们来看看Spring的核心组件——IoC容器。IoC容器是Spring的核心,它负责管理对象的生命周期和对象之间的依赖关系。通过XML配置或基于注解的方式,我们可以告诉IoC容器如何创建和装配对象。在源码中,`...
根据提供的信息来看,本次的任务是围绕“精通Spring”这一主题展开深入探讨,但由于给定的部分内容与主题不符,主要涉及一个二手书籍交易平台的信息,这里我们将忽略这部分内容,转而聚焦于Spring框架的核心概念、...
43、指出在springaop中concern和cross-cuttingconcern的不同之处。 在Spring AOP中,concern指的是应用程序中的业务逻辑代码,而cross-cutting concern是横切关注点,如日志记录、事务管理等,这些关注点贯穿多个...
5. **Spring MVC**:提供了一种模式化的Web应用程序架构,使得开发MVC模式的应用变得简单。 6. **Spring Web Services**:为构建基于SOAP和WSDL的Web服务提供了支持。 标签“spring框架源码”表明这个压缩包可能...
首先,我们来看Spring 3.0.0版本。这个版本是一个里程碑式的更新,引入了许多新特性,如Java配置、AOP改进、基于注解的事务管理等。Java配置允许开发者使用Java类替代XML配置,使代码更加简洁且易于维护。AOP(面向...
5. **Testing**:`spring-test`模块支持集成测试,它与JUnit和其他测试框架结合使用,使得测试Spring应用程序变得简单。 6. **Instrumentation**:`spring-instrument`和`spring-instrument-tomcat`模块用于服务器...
5. **Web MVC**:Spring的Model-View-Controller(MVC)框架使得构建Web应用程序变得更加简单,它提供了一种解耦的方式来组织前端和后端代码。 6. **Spring Boot**:为简化Spring应用的初始搭建和运行过程,Spring ...
根据读者和专业评论者的反馈来看,《Spring in Action》不仅是一本技术手册,还融合了良好的软件设计思想和模式,使得学习过程更加轻松愉快。 - **读者评价**:多位读者提到这本书不仅覆盖了Spring框架的所有基础...
首先,我们来看"spring-framework-4.3.6.RELEASE"这个目录,这是Spring框架的4.3.6版本。Spring框架分为多个模块,包括Core Container(核心容器)、Data Access/Integration(数据访问/集成)、Web、AOP、...
首先,我们来看看 Spring 框架的核心概念: 1. **依赖注入(Dependency Injection, DI)**:Spring 的核心特性之一,通过容器管理对象的生命周期和依赖关系,降低了组件之间的耦合度。DI 可以通过构造器注入、...
Spring框架是Java开发中不可或缺的一部分,它以其强大的依赖注入、AOP(面向切面编程)以及模块化...在阅读源码的过程中,不仅要看懂代码,更要理解设计模式和架构思想,这样才能真正将Spring的精髓运用到日常开发中。