spring AOP原理分析:静态代理;JDK实现接口动态代理;Cglib继承父类代理;SpringAop的责任链模式调用

34 篇文章 0 订阅

普通静态代理

代理类和真实类都需要实现同一个接口

接口

package com.fchan.layui.represent.service;
/**
 * 静态代理demo
 */
public interface Subject {
    public void print();
}

真实类

package com.fchan.layui.represent.service.impl;

import com.fchan.layui.represent.service.Subject;

public class RealSubject implements Subject {
    @Override
    public void print() {
        System.out.println("被代理的对象(即真实对象)的print方法");
    }
}

代理类

package com.fchan.layui.represent.service.impl;

import com.fchan.layui.represent.service.Subject;
import lombok.extern.slf4j.Slf4j;

@Slf4j
public class Proxy implements Subject {

    private RealSubject realSubject;

    public Proxy(RealSubject realSubject) {
        this.realSubject = realSubject;
    }

    @Override
    public void print() {
      log.info("代理对象开始干活了");
      //被代理的对象处理业务
      realSubject.print();
      log.info("代理对象干活结束");
    }
}

使用demo

/**
 * 静态代理demo
 */
@Test
public void testRepresent(){
	Subject subject = new Proxy(new RealSubject());
	subject.print();
}

普通的静态代理有很大的局限性,如果需要代理的目标类实现的接口方法很多.并且这些方法都需要进行扩展的话,需要写很多.所以JDK动态代理就可以很好的解决这个问题,只需要写一个具体增强实现的类实现InvocationHandler接口.就可以在invoke方法里处理被代理对象实现的所有接口方法.

JDK动态代理

代理目标类实现的接口,因为JDK动态代理是基于接口的,接口没有的方法是代理不到的.

package com.fchan.layui.represent.service;
/**
 * 接口,代理目标类实现了这个接口
 */
public interface Subject {
    public void print();
}

被代理的目标类实现了这个接口

package com.fchan.layui.represent.service.impl;

import com.fchan.layui.represent.service.Subject;

public class RealSubject implements Subject {
    @Override
    public void print() {
        System.out.println("被代理的对象(即真实对象)的print方法");
    }
}

具体去增强实现的辅助类,到这里还没去使用JDK的动态代理,这里这个增强辅助类和这个代理目标类还没有啥关系

package com.fchan.layui.represent.service;

import com.fchan.layui.represent.service.impl.RealSubject;
import lombok.extern.slf4j.Slf4j;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * JDK的动态代理,利用InvocationHandler生成代理类
 */

@Slf4j
public class JdkProxySubject implements InvocationHandler {


    private RealSubject realSubject;

    public JdkProxySubject(RealSubject realSubject) {
        this.realSubject = realSubject;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

        log.info("开始执行动态代理的逻辑,类似spring aop的@Before通知");
        Object result = null;

        try {
            //利用反射调用目标对象的方法
            result = method.invoke(realSubject,args);
        } catch (IllegalAccessException e) {
        	//代理类不是真正处理的类,这里接着把异常往外面抛
            e.printStackTrace();
            throw e;
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
            throw e;
        } catch (InvocationTargetException e) {
            e.printStackTrace();
            throw e;
        } finally {
            log.info("执行finally代码块,相当于springaop的@After通知");
        }

        return result;
    }
}
/**
 * JDK的动态代理
 * 需要通过接口来实现,即目标类需要实现一个业务接口
 * loader:一个ClassLoader对象,定义了由哪个ClassLoader对象来对生成的代理对象进行加载
 *
 * interfaces:一个Interface对象的数组,表示的是我将要给我需要代理的对象提供一组什么接口
 * ,如果我提供了一组接口给它,那么这个代理对象就宣称实现了该接口(多态),这样我就能调用这组接口中的方法了
 *
 * h:一个InvocationHandler接口,表示代理实例的调用处理程序实现的接口。每个代理实例都具有一个关联的调用处理程序。
 * 对代理实例调用方法时,将对方法调用进行编码并将其指派到它的调用处理程序的 invoke 方法(传入InvocationHandler接口的子类)
 */
@Test
public void testJDKDynamicProxy(){
	RealSubject realSubject = new RealSubject();
	realSubject.getClass().getInterfaces();
	Subject subject = (Subject) java.lang.reflect.Proxy.newProxyInstance(this.getClass().getClassLoader()
			,new Class[]{Subject.class},new JdkProxySubject(new RealSubject()));
	//其实这里的JdkProxySubject就是实现了InvocationHandler接口的一个类,也可以直接通过匿名类的形式创建
	/**Subject subject = (Subject) java.lang.reflect.Proxy.newProxyInstance(this.getClass().getClassLoader()
			,new Class[]{Subject.class},new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                return null;
            }
        });*/
	subject.print();
}

那么JDK究竟帮我们生成了一个怎么样的代理类呢,我们可以在获取代理对象之前也就是Proxy.newProxyInstance之前加一行参数

//将生成的字节码保存下来
System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles","true");

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

Cglib动态代理,类似于jdk代理也要实现一个接口—MethodInterceptor接口

看了上面的2种代理方式后,实现cglib代理就轻车熟路啦

先创建一个代理类,实现MethodInterceptor接口

package com.fchan.layui.represent.service;

import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;

public class CglibDemoInterceptor implements MethodInterceptor {
    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println("cglib represent before");
        Object result = null;
        try {
            result = methodProxy.invokeSuper(o,objects);
        } catch (Throwable throwable) {
            throwable.printStackTrace();
            throw throwable;
        } finally {
            System.out.println("cglib represent finally");
        }
        return result;
    }
}

然后用代理类去继承代理目标类

@Test
public void testCglibProxy(){
	Enhancer enhancer = new Enhancer();
	//设置父类也就是需要代理增强的业务类
	enhancer.setSuperclass(RealSubject.class);
	//具体的实现了MethodInterceptor接口的子类,也就是增强目标类的代理类
	enhancer.setCallback(new CglibDemoInterceptor());
	Subject subject = (Subject) enhancer.create();
	subject.print();
}

代理成功~
在这里插入图片描述

现在我们知道有JDK动态代理和Cglib动态代理了,那么这两者有啥区别呢

  1. JDK动态代理只能代理实现了接口的类,并且只能代理接口拥有的方法
  2. Cglib动态代理不能代理父类中privatefinal的方法,因为声明了这两个关键字的这些方法对于子类是不可见的.当然对于声明了finalstatic的类也是无法代理的,因为不能被继承
    .

SpringAop对JDK代理和Cglib代理的选择

  • 如果目标对象实现了接口,则默认采用JDK动态代理
  • 如果目标对象没有实现接口,则采用Cglib进行动态代理
  • 如果目标对象实现了接口,且强制cglib代理,则使用cglib代理

SpringAop实现代理类的流程

在这里插入图片描述

在这里插入图片描述

强制进行Cglib代理

在这里插入图片描述

责任链模式调用demo

声明抽象类

package com.fchan.layui.chainsMethods;

public abstract class Handler {

    private Handler successor;

    public Handler getSuccessor() {
        return successor;
    }

    public void setSuccessor(Handler successor) {
        this.successor = successor;
    }

    public void handlerProcess(){
        execution();
        if(null != successor){
            successor.handlerProcess();
        }
    }

    public abstract void execution();

}

责任链实现demo

package com.fchan.layui.chainsMethods;

public class Client {

    static class  HandlerA extends Handler{

        @Override
        public void execution() {
            System.out.println("HandlerA");
        }
    }

    static class  HandlerB extends Handler{

        @Override
        public void execution() {
            System.out.println("HandlerB");
        }
    }

    static class  HandlerC extends Handler{

        @Override
        public void execution() {
            System.out.println("HandlerC");
        }
    }

    public static void main(String[] args) {
        Handler handlerA = new HandlerA();
        Handler handlerB = new HandlerB();
        Handler handlerC = new HandlerC();

        handlerA.setSuccessor(handlerB);
        handlerB.setSuccessor(handlerC);

        handlerA.handlerProcess();
    }

}

SpringAop中责任链的实现

实际处理的方法

package com.fchan.layui.chainsMethods.springaopChain;

public abstract class ChainHandler {


    public void execution(Chain chain){
        handlerProcess();
        chain.proceed();
    }

    protected abstract void handlerProcess();

}

责任链维护类

package com.fchan.layui.chainsMethods.springaopChain;

import java.util.List;

public class Chain {

    List<ChainHandler> chainHandlers;

    private int index = 0;

    public Chain(List<ChainHandler> chainHandlers) {
        this.chainHandlers = chainHandlers;
    }

    public List<ChainHandler> getChainHandlers() {
        return chainHandlers;
    }

    public void setChainHandlers(List<ChainHandler> chainHandlers) {
        this.chainHandlers = chainHandlers;
    }

    protected void proceed(){
        if(index >= this.getChainHandlers().size()){
            return;
        }
        this.getChainHandlers().get(index ++ ).execution(this);
    }

}

调用实现,维护责任链顺序的客户端

package com.fchan.layui.chainsMethods.springaopChain;

import java.util.Arrays;
import java.util.List;

public class ChainClient {

    static class ChainHandlerA extends ChainHandler{

        @Override
        protected void handlerProcess() {
            System.out.println("chain handlerA");
        }
    }

    static class ChainHandlerB extends ChainHandler{

        @Override
        protected void handlerProcess() {
            System.out.println("chain handlerB");
        }
    }

    static class ChainHandlerC extends ChainHandler{

        @Override
        protected void handlerProcess() {
            System.out.println("chain handlerC");
        }
    }

    public static void main(String[] args) {
        List<ChainHandler> list = Arrays.asList(
                new ChainHandlerA(),
                new ChainHandlerB(),
                new ChainHandlerC()
        );
        Chain chain = new Chain(list);
        chain.proceed();

    }

}

spring aop的责任链调用也是如此
类名ReflectiveMethodInvocation

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值