Spring 动态代理
AOP功能强大,但是spring是如何来实现AOP技术的呢?
SPRING是通过动态代理来实现AOP的,SPRING内部提供了2种实现机制
1.如果是有接口声明的类进行AOP,spring调用的是java.lang.reflection.Proxy类来做处理
2.如果是没有接口声明的类呢?SPRING通过CGLIB包和内部类来实现
我们自己也可以来试试
1.jdk proxy方式
先来一个接口
IHelloWorld.java
再来一个实现
HelloWorld.java
代理类
DefaultInvocationHandler.java
测试类
Test.java
2.用CGLIB包实现,首先不要忘了引入那个包
代理类(没用内部类,看起来清楚点)
测试类
SPRING是通过动态代理来实现AOP的,SPRING内部提供了2种实现机制
1.如果是有接口声明的类进行AOP,spring调用的是java.lang.reflection.Proxy类来做处理
- org.springframework.aop.framework.JdkDynamicAopProxy
- public Object getProxy(ClassLoader classLoader) {
- if (logger.isDebugEnabled()) {
- Class targetClass = this.advised.getTargetSource().getTargetClass();
- logger.debug("Creating JDK dynamic proxy" +
- (targetClass != null ? " for [" + targetClass.getName() + "]" : ""));
- }
- Class[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised);
- return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
- }
- org.springframework.aop.framework.ReflectiveMethodInvocation
- public Object proceed() throws Throwable {
- // We start with an index of -1 and increment early.
- if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
- return invokeJoinpoint();
- }
- Object interceptorOrInterceptionAdvice =
- this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
- if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
- // Evaluate dynamic method matcher here: static part will already have
- // been evaluated and found to match.
- InterceptorAndDynamicMethodMatcher dm =
- (InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
- if (dm.methodMatcher.matches(this.method, this.targetClass, this.arguments)) {
- return dm.interceptor.invoke(this);
- }
- else {
- // Dynamic matching failed.
- // Skip this interceptor and invoke the next in the chain.
- return proceed();
- }
- }
- else {
- // It's an interceptor, so we just invoke it: The pointcut will have
- // been evaluated statically before this object was constructed.
- return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
- }
- }
2.如果是没有接口声明的类呢?SPRING通过CGLIB包和内部类来实现
- private static class StaticUnadvisedInterceptor implements MethodInterceptor, Serializable {
- private final Object target;
- public StaticUnadvisedInterceptor(Object target) {
- this.target = target;
- }
- public Object intercept(Object proxy, Method method, Object[] args,
- MethodProxy methodProxy) throws Throwable {
- Object retVal = methodProxy.invoke(target, args);
- return massageReturnTypeIfNecessary(proxy, target, retVal);
- }
- }
- /**
- * Method interceptor used for static targets with no advice chain, when the
- * proxy is to be exposed.
- */
- private static class StaticUnadvisedExposedInterceptor implements MethodInterceptor, Serializable {
- private final Object target;
- public StaticUnadvisedExposedInterceptor(Object target) {
- this.target = target;
- }
- public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
- Object oldProxy = null;
- try {
- oldProxy = AopContext.setCurrentProxy(proxy);
- Object retVal = methodProxy.invoke(target, args);
- return massageReturnTypeIfNecessary(proxy, target, retVal);
- }
- finally {
- AopContext.setCurrentProxy(oldProxy);
- }
- }
- }
- /**
- * Interceptor used to invoke a dynamic target without creating a method
- * invocation or evaluating an advice chain. (We know there was no advice
- * for this method.)
- */
- private class DynamicUnadvisedInterceptor implements MethodInterceptor, Serializable {
- public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
- Object target = advised.getTargetSource().getTarget();
- try {
- Object retVal = methodProxy.invoke(target, args);
- return massageReturnTypeIfNecessary(proxy, target, retVal);
- }
- finally {
- advised.getTargetSource().releaseTarget(target);
- }
- }
- }
- /**
- * Interceptor for unadvised dynamic targets when the proxy needs exposing.
- */
- private class DynamicUnadvisedExposedInterceptor implements MethodInterceptor, Serializable {
- public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
- Object oldProxy = null;
- Object target = advised.getTargetSource().getTarget();
- try {
- oldProxy = AopContext.setCurrentProxy(proxy);
- Object retVal = methodProxy.invoke(target, args);
- return massageReturnTypeIfNecessary(proxy, target, retVal);
- }
- finally {
- AopContext.setCurrentProxy(oldProxy);
- advised.getTargetSource().releaseTarget(target);
- }
- }
- }
我们自己也可以来试试
1.jdk proxy方式
先来一个接口
IHelloWorld.java
- package kris.aop.test;
- public interface IHelloWorld {
- public void print(String name);
- public void write(String sth);
- }
再来一个实现
HelloWorld.java
- package kris.aop.test;
- public class HelloWorld implements IHelloWorld {
- public void print(String name){
- System.out.println("HelloWorld "+name);
- }
- public void write(String sth) {
- System.out.println("write "+sth);
- }
- }
代理类
DefaultInvocationHandler.java
- package kris.aop.test;
- import java.lang.reflect.InvocationHandler;
- import java.lang.reflect.Method;
- public class DefaultInvocationHandler implements InvocationHandler {
- /**
- * 替换外部class调用的方法
- * obj 外部已经已经包装好InvocationHandler的实例
- * method 外部方法
- * args 方法参数
- */
- public Object invoke(Object obj, Method method, Object[] args)
- throws Throwable {
- String s1 []={"kris"};
- String s2 []={"anyone"};
- IHelloWorld ihw=new HelloWorld();
- System.out.println("start!");
- method.invoke(ihw,args);
- method.invoke(ihw,s1);
- Object o=method.invoke(ihw,s2);
- System.out.println("stop!");
- return o;
- }
- }
测试类
Test.java
- package kris.aop.test;
- import java.lang.reflect.InvocationHandler;
- import java.lang.reflect.Proxy;
- public class Test {
- public static void main(String args []){
- Class clazz = new HelloWorld().getClass();
- ClassLoader cl = clazz.getClassLoader();
- Class classes [] = clazz.getInterfaces();
- InvocationHandler ih=new DefaultInvocationHandler();
- //用InvocationHandler给HelloWorld进行AOP包装
- IHelloWorld ihw=(IHelloWorld) Proxy.newProxyInstance(cl,classes,ih);
- ihw.print("test");
- ihw.write("test");
- }
- }
2.用CGLIB包实现,首先不要忘了引入那个包
- package kris.aop.cglib.test;
- public class HelloWorld {
- public void print(String name){
- System.out.println("HelloWorld "+name);
- }
- public void write(String sth) {
- System.out.println("write "+sth);
- }
- public void print(){
- System.out.println("HelloWorld");
- }
- }
代理类(没用内部类,看起来清楚点)
- package kris.aop.cglib.test;
- import java.lang.reflect.Method;
- import net.sf.cglib.proxy.MethodInterceptor;
- import net.sf.cglib.proxy.MethodProxy;
- public class MethodInterceptorImpl implements MethodInterceptor {
- public Object intercept(Object obj, Method method, Object[] args,
- MethodProxy proxy) throws Throwable {
- System.out.println(method);
- proxy.invokeSuper(obj, args);
- return null;
- }
- }
测试类
- package kris.aop.cglib.test;
- import net.sf.cglib.proxy.Enhancer;
- public class Test {
- public static void main(String[] args) {
- Enhancer enhancer = new Enhancer();
- enhancer.setSuperclass(HelloWorld.class);
- //设置回调方法实现类
- enhancer.setCallback(new MethodInterceptorImpl());
- //实例化已经添加回调实现的HELLOWORLD实例
- HelloWorld my = (HelloWorld) enhancer.create();
- my.print();
- }
- }