Spring关于AOP的学习1(使用jdk中的动态代理--Proxy)

AOP:面向切面编程,将某段代码动态切入指定方法指定位置进行运行的这种编程方式。
1、动态代理–Proxy的使用
这里以加减乘除为例子。
创建加减乘除的方法接口:Calculator.java

package com.msb.service;

public interface Calculator {
    public Integer add(Integer i,Integer j) throws NoSuchMethodException;
    public Integer sub(Integer i,Integer j) throws NoSuchMethodException;
    public Integer mul(Integer i,Integer j) throws NoSuchMethodException;
    public Integer div(Integer i,Integer j) throws NoSuchMethodException;
}

创建继承接口的方法具体实现类:MyCalculator.java

package com.msb.service;

import com.msb.util.LogUtil;
import org.omg.PortableInterceptor.INACTIVE;

import java.lang.reflect.Method;

public class MyCalculcator implements Calculator {
    public Integer add(Integer i, Integer j) throws NoSuchMethodException {
        Integer result = i+j;
        return result;
    }

    public Integer sub(Integer i, Integer j) throws NoSuchMethodException {
        Integer result = i-j;
        return result;
    }

    public Integer mul(Integer i, Integer j) throws NoSuchMethodException {
        Integer result = i*j;
        return result;
    }

    public Integer div(Integer i, Integer j) throws NoSuchMethodException {
        Integer result = i/j;
        return result;
    }
}

创建动态代理类:CalculcatorProxy.java

package com.msb.proxy;

import com.msb.service.Calculator;
import com.msb.util.LogUtil;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.Arrays;

/**
 * 必须要有接口,若没有接口不能使用,这种方式使用的是jdk的reflect下的类
 * 若无接口,可以使用cglib
 * Spring中使用了两种动态代理,Proxy、cglib
 */
public class CalculcatorProxy {
    public static Calculator getCalculcator(final Calculator calculator){      //匿名类里边无法调用外部函数的值
        ClassLoader loader = calculator.getClass().getClassLoader();    //类装载器
        Class[] interfaces = calculator.getClass().getInterfaces();      //获取所有接口
        //用来执行被代理类需要执行的方法
        InvocationHandler handler = new InvocationHandler() {
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {        //代理对象、代理方法、方法参数
                Object result = null;
                try{
                    LogUtil.start(method,args);
                    //invoke:开始调用被代理类的方法
                    result = method.invoke(calculator,args);
                    LogUtil.stop(method,result);
                }catch (Exception e){
                    LogUtil.logException(method,e);
                    e.printStackTrace();
                }finally {
                    LogUtil.logFinally(method);
                }
                return result;
            }
        };

        Object o = Proxy.newProxyInstance(loader, interfaces, handler);     //动态代理
        return (Calculator) o;
    }
}

动态代理主要使用的是Proxy.newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)方法。
方法中的参数:
(1)ClassLoader loader:类的装载器,可以通过类名.getClass().getClassLoader得到;
(2)Class<?>[] interfaces:interface是接口,interfaces便是全部接口,这里获取的应该是代理类的全部接口;
(3)InvocationHandler h:定义这个类的对象后发现还有需具体实现的方法invoke():执行代理类需要执行的方法

测试类:MyTest.java

import com.msb.proxy.CalculcatorProxy;
import com.msb.service.Calculator;
import com.msb.service.MyCalculcator;
import org.junit.Test;

public class MyTest {
    //这里使用的是junit
    @Test
    public void test01() throws NoSuchMethodException {
        Calculator calculcator = CalculcatorProxy.getCalculcator(new MyCalculcator());
        calculcator.add(1,2);
        System.out.println(calculcator.getClass());
    }
}

总结:这里使用的其实是jdk提供的动态代理类,Spring中是通过注解来实现,但是底层依赖的还是动态代理。
这个案例其实就是想说,若不使用动态代理,在每个方法中都需要 添加相同的代码块,使用动态代理其实就是将这部分代码封装成一个类,然后通过动态代理中调用这个类中的方法,还有实现代码逻辑的操作方法,也就是其他功能都是通过代码模块化实现,最终使用动态代理Proxy.newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)去实现,而 方法前面两个参数都可以直接获取,主要是第三个参数,第三个参数中可以写入需要代理的方法。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值