spring aop 拦截类 对Spring AOP框架实现的结构分析(2)

电脑杂谈  发布时间:2018-01-10 07:09:05  来源:网络整理

AOP代理(AOP proxy):即被增强(advise)的对象引用--也就是说,AOP增强将在其上执行的这样一个对象引用。

目标对象(target object):位于链末端的对象实例--这个概念只存在于那些使用了拦截机制的框架之中。

注:上述概念描述引自《Expert One-on-One J2EE Development without EJB》中第八章对AOP概念描述部分,更多精彩部分可以参阅本章的完整内容。

上述概念已被Spring AOP框架很好的实现,相关组件:

Advisor 组件,

Advice 组件,

Pointcut 组件,

Advised 组件,

AopProxy 组件,

AopProxyFactory 组件,

图1.

图1是对增强、切入点、方面、AOP代理之间依赖关系的全景图。

增强和切入点组成一个方面,方面信息与目标对象信息被组织到Advised中,AopProxyFactory通过Advised中保存的信息生成AopProxy

对象,调用AopProxy.getProxy()方法即可获得增强后的对象。

这里要着重了解的是不同的增强子类型,不同的切入点子类型,

对于不同的切入点子类型最重要的两类型:静态切入点,动态切入点,

静态切入点:根据部署阶段的信息选择增强,如“拦截特定类的所有getter方法”;

动态切入点:根据运行时的信息选择增强,如“如果某方法的返回值为null,则将其纳入某切入点”。

图2.

图2是对图1中Advisor与Pointcut的实现细化,图中类之间的关系直观上有点乱,但细看下关系还是相当清晰的,

以Advisor结尾的是方面类型,以Pointcut结尾的是切入点类型,

Advisor与Pointcut的复用关系分两类:一类是组合复用,另一类是具体继承复用,

spring aop 拦截类_spring aop实现原理_spring aop方法

组合复用例子 如:RegexpMethodPointcutAdvisor 与 AbstractRegexpMethodPointcut之间的关系,

NameMatchMethodPointcutAdvisor 与 NameMatchMethodPointcut之间的关系,

具体继承复用例子 如:StaticMethodMatcherPointcutAdvisor 与 StaticMethodMatcherPointcut 之间的关系,

DynamicMethodMatcherPointcutAdvisor 与 DynamicMethodMatcherPointcut 之间的关系,

图3.

图3是对图1中生成AopProxy对象的实现细化,

AopProxyFactory通过AdvisedSupport提供的信息生成AopProxy对象,AopProxy对象的生成分两类方式:一类是动态代理,另一类是字节码增强;

需要注意的是,ProxyFactory与ProxyFactoryBean并不是功能实现的必要部分,主要目的为编程式使用代理提供便利的API。

下面是一个简单的sample:

//目标对象接口.
public interface Target {
	public String play(int arg);
}
//目标对象实现.
public class TargetImpl implements Target {

	public String play(int arg) {
		 System.out.println("play method....");
		return "[Target:]" + arg;
	}
}
//前置增强
public class MyBeforeAdvice implements MethodBeforeAdvice {
	public void before(Method method, Object[] args, Object target)
			throws Throwable {
		 System.out.println(method.getName());
		 System.out.println("before method!");
	}
}
//后置增强
public class MyAfterAdvice implements AfterReturningAdvice {
	public void afterReturning(Object returnValue, Method method,
			Object[] args, Object target) throws Throwable {
		 System.out.println(returnValue + ":after method"); 
	}
}
//切入点实现
public class MyPointcut implements Pointcut {

	public ClassFilter getClassFilter() {
		 
		return new ClassFilter() {

			public boolean matches(Class arg0) {
				if (arg0 == TargetImpl.class) {
					return true;
				}
				return false;
			}
			
		};
	}

	public MethodMatcher getMethodMatcher() {
		 
		return new MethodMatcher() {

			public boolean isRuntime() {
				 
				return false;
			}

			public boolean matches(Method arg0, Class arg1) {
				
				if ("play".equals(arg0.getName())) {
					return true;
				}
				return false;
			}

			public boolean matches(Method arg0, Class arg1, Object[] arg2) {
				System.out.println("aaaaaa");
				if ("play".equals(arg0.getName())) {
					return true;
				}
				return false;
			}
			
		};
	}

}
public class Main {
	public static void main(String[] args) {
		 Target target = new TargetImpl();   //目标对象
		 Advice beforeAdvice = new MyBeforeAdvice(); //增强
		 Pointcut pointcut = new MyPointcut(); //切入点
		 DefaultPointcutAdvisor dda = new DefaultPointcutAdvisor(); //切面
		 dda.setAdvice(beforeAdvice);
		 dda.setPointcut(pointcut);
		 
		 AdvisedSupport advisedSupport = new AdvisedSupport(); //提供基本的编程方式,
		 advisedSupport.addAdvisor(dda);
		 advisedSupport.addAdvice(new MyAfterAdvice());
		 advisedSupport.addInterface(Target.class);
		 advisedSupport.setTarget(target);
		 AopProxy aopProxy = new DefaultAopProxyFactory().createAopProxy(advisedSupport);
		 Target proxy = (Target)aopProxy.getProxy();
		 System.out.println(proxy.play(200));
		 
		 ProxyFactory proxyFactory = new ProxyFactory();  //提供便利的编程方式.
		 proxyFactory.addAdvisor(dda);
		 proxyFactory.addInterface(Target.class);
		 proxyFactory.setTarget(target);
		 Target proxy2 = (Target)proxyFactory.getProxy();
		 System.out.println(proxy2.play(201));
		 
		 ProxyFactoryBean proxyFactoryBean = new ProxyFactoryBean(); //提供便利的配置方式
		 proxyFactoryBean.addAdvisor(dda);
		 proxyFactoryBean.addInterface(Target.class);
		 proxyFactoryBean.setTarget(target);
		 Target proxy3 = (Target)proxyFactoryBean.getObject();
		 System.out.println(proxy3.play(232));
	}
}


本文来自电脑杂谈,转载请注明本文网址:
https://www.pc-fly.com/a/jisuanjixue/article-59495-2.html

相关阅读
    发表评论  请自觉遵守互联网相关的政策法规,严禁发布、暴力、反动的言论

    热点图片
    拼命载入中...