您的位置:首页 > 编程语言 > Java开发

Spring高级程序设计 5 Spring AOP基础

2011-11-21 17:28 295 查看
1AOP概念

AOP的核心概念:

连接点(jointpoint):一个连接点是一个程序执行过程中的特定点。

通知(advice):在某一特定的连接点处运行的代码成为“通知”。

切入点(pointcut):切入点是用来定义某一个通知该何时执行的一组连接点。

方面(aspect):通知和切入点的组合叫做方面。

织入(weaving):织入是将方面真正的加入程序代码的过程。

目标(target):如果一个对象的执行过程受到某个AOP操作的修改,那么他就叫做一个目标对象,也成为通知对象。

引入(introduction):通过引入,我们可以在一个对象中加入新的方法或者字段,以改变他的结构。

2AOP的类型

两种类型AOP:静态AOP和动态AOP。

静态代理:

代理对象与被代理对象必须实现同一个接口。

demo:

view
plaincopy
to clipboardprint?

package cn.partner4java.proxy.staticproxy;

/**

*
静态代理,统一接口

*
@author partner4java

*

*/

public interface IHello
{

/**

* 可以带来的统一方法

* @param name

*/

public void hello(String
name);

}

view
plaincopy
to clipboardprint?

package cn.partner4java.proxy.staticproxy;

/**

*
被代理的对象,需要借助代理对象加入日志

*
@author partner4java

*

*/

public class HelloSpeaker implements IHello
{

public void hello(String
name) {

System.out.println("Hello
" +
name);

}

}

view
plaincopy
to clipboardprint?

package cn.partner4java.proxy.staticproxy;

/**

*
代理对象,给被代理对象添加日志

*/

public class HelloProxy implements IHello
{

private IHello
iHello;

public HelloProxy(IHello
iHello) {

super();

this.iHello
= iHello;

}

public void hello(String
name) {

System.out.println("记录日志");

iHello.hello(name);

}

}

view
plaincopy
to clipboardprint?

package cn.partner4java.proxy.staticproxy;

/**

*
调用

*
@author partner4java

*

*/

public class ProxyDemo
{

public static void main(String[]
args) {

IHello
iHello = new HelloProxy(new HelloSpeaker());

iHello.hello("long");

}

}

动态代理:

动态代理区别于静态带来实现的地方在于织入过程是在运行时动态进行的。自己实现一般实现java.lang.reflect.InvocationHandler接口。

例子:

view
plaincopy
to clipboardprint?

package cn.partner4java.proxy.dynamicproxy;

public interface IHello
{

public void hello(String
name);

}

view
plaincopy
to clipboardprint?

package cn.partner4java.proxy.dynamicproxy;

/**

*
被代理的对象,需要借助代理对象加入日志

*
@author partner4java

*

*/

public class HelloSpeaker implements IHello
{

public void hello(String
name) {

System.out.println("Hello
" +
name);

}

}

view
plaincopy
to clipboardprint?

package cn.partner4java.proxy.dynamicproxy;

import java.lang.reflect.InvocationHandler;

import java.lang.reflect.Method;

import java.lang.reflect.Proxy;

/**

*
动态代理对象

*
@author partner4java

*

*/

public class LogHandler implements InvocationHandler
{

private Object
delegate;

public Object
bind(Object delegate){

this.delegate
= delegate;

return Proxy.newProxyInstance(delegate.getClass().getClassLoader(),

delegate.getClass().getInterfaces(), this);

}

/**

* 代理对象,这里面还可以改变原有的方法

*/

public Object
invoke(Object proxy, Method method, Object[] args)

throws Throwable
{

Object
result = null;

try {

System.out.println("添加日志");

result
= method.invoke(delegate, args);

} catch (Exception
e) {

e.printStackTrace();

}

return null;

}

}

view
plaincopy
to clipboardprint?

package cn.partner4java.proxy.dynamicproxy;

/**

*
测试

*
@author partner4java

*

*/

public class ProxyDemo
{

public static void main(String[]
args) {

LogHandler
logHandler = new LogHandler();

IHello
iHello = (IHello) logHandler.bind(new HelloSpeaker());

iHello.hello("long");

}

}

3Spring中的AOP

利用ProxyFactory连接CGLIB简单实现AOP:


加入包aopalliance.jar\cglib-nodep-2.1_3.jar

demo:

view
plaincopy
to clipboardprint?

package cn.partner4java.proxy.proxyfactory;

/**

*
被代理的对象

*
@author partner4java

*

*/

public class MessageWriter
{

public void writeMessage(){

System.out.println("world!");

}

}

view
plaincopy
to clipboardprint?

package cn.partner4java.proxy.proxyfactory;

import org.aopalliance.intercept.MethodInterceptor;

import org.aopalliance.intercept.MethodInvocation;

/**

*
装饰者<br/>

*
MethodInterceptor接口是对方法调用连接点实现包围通知的AOP联盟标准接口

*
@author partner4java

*

*/

public class MessageDecorator implements MethodInterceptor{

public Object
invoke(MethodInvocation invocation) throws Throwable
{

System.out.print("Hello
");

Object
retVal = invocation.proceed();

return retVal;

}

}

view
plaincopy
to clipboardprint?

package cn.partner4java.proxy.proxyfactory;

import org.springframework.aop.framework.ProxyFactory;

/**

*
调用组装

*
这里最重要的部分是我们使用ProxyFactory来创建一个目标对象代理,同时织入通知

*
@author partner4java

*

*/

public class HelloWorldWeaver
{

public static void main(String[]
args) {

//目标

MessageWriter
target = new MessageWriter();

//create
the proxy

ProxyFactory
proxyFactory = new ProxyFactory();

proxyFactory.addAdvice(new MessageDecorator());

proxyFactory.setTarget(target);

//获取返回被代理的目标

MessageWriter
proxy = (MessageWriter) proxyFactory.getProxy();

target.writeMessage();

System.out.println("---");

proxy.writeMessage();

// 后台打印:

// world!

// ---

// World
world!

}

}

Spring内部两种实现代理的方法:JDK动态代理和CGLIB代理。

ProxyFactory类控制着Spring AOP中的织入和创建代理的过程。

141-155各种通知(前置、后置等等)

4Spring里的通知者和切入点

155-176 讲解手工实现接口来实现切入点的方法

5代理详解

代理的核心就是拦截方法调用,并在需要的时候执行匹配某方法的通知链。

和CGLIB不同的是,JDK代理只能代理接口,不能代理类。

使用JDK代理时,如何处理一个特定的方法调用的决定是在程序运行时做出的,也就是在每次方法被调用时。使用CGLIB代理可以边开这种处理方法,CGLIB会在运行中随时为代理创建新类的字节码,并尽可能的重用已经生成的类的字节码。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: