SpringAop学习(二)

简介: SpringAop学习(二)

静态代理的缺点

当我们的目标类多个方法时,使用静态代理就需要为这多个方法写差不多的操作,这样会使得我们的代码变的越来越臃肿。我们就可以使用动态代理的方式来处理这个问题

动态代理

动态代理的两种实现方法:基于接口的代理使用jdk的方式,基于继承的代理使用cglib

jdk动态代理

Jdk动态代理只能代理实现接口的类,没有实现接口的类不能实现JDK的动态代理。

Java动态代理类位于java.lang.reflect包下,一般主要涉及到以下两个类:

(1)Interface InvocationHandler :该接口中仅定义了一个方法public object invoke(Object obj;Method method, Object[] args)在实际使用时,第一个参数obj一般是指代理类, method是被代理的方法, args为该方法的参数数组。 这个抽象方法在代理类中动态实现。


(2)Proxy :该类即为动态代理类

newProxyInstance方法用来返回一个代理对象,这个方法总共有3个参数,

  • ClassLoader loader:一个ClassLoader对象,定义了由哪个ClassLoader对象来对生成的代理对象进行加载
  • Class<?>[] interfaces:一个Interface对象的数组,表示的是我将要给我需要代理的对象提供一组什么接口,如果我提供了一组接口给它,那么这个代理对象就宣称实现了该接口(多态),这样我就能调用这组接口中的方法了
  • InvocationHandler h:一个InvocationHandler对象,表示的是当我这个动态代理对象在调用方法的时候,会关联到哪一个InvocationHandler对象上

案例

接口

public interface Subject {
    void work();
}

真实对象

public class RealSubject implements Subject{
    @Override
    public void work() {
        System.out.println("----------吃饭");
    }
}

jdk动态代理类

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 {
        System.out.println("------买菜");
        Object result=null;
        try {
            result = method.invoke(realSubject,args);
        } catch (Exception e) {
            e.printStackTrace();
        }  finally {
            System.out.println("------洗碗");
        }
        return result;
    }
}

客户端调用

public class Client {
    public static void main(String[] args) {
        Subject subject = (Subject) Proxy.newProxyInstance(RealSubject.class.getClassLoader(),
                RealSubject.class.getInterfaces(),
                new JdkProxySubject(new RealSubject()));
        subject.work();
    }
}
  • RealSubject.class.getInterfaces() 该方法是获取到RealSubject实现的接口,如果有RealSubject实现多个接口都可通过该方法获取到。
  • RealSubject.class.getInterfaces()可以替换成new Class[]{Subject.class}的效果是一样的

20190803015630300.png

效果

20190803014457117.png

cglib动态代理

注意事项:

  • cglib是通过继承来实现动态代理的
  • 无法对static,final类进行代理
  • 无法对private,static方法进行代理

案例

真实对象,不需要接口

public class RealSubject{
    public void work() {
        System.out.println("----------cglib---吃饭");
    }
}

代理对象

public class DemoMethodInterceptor implements MethodInterceptor{
    @Override
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        System.out.println("before in cglib------买菜");
        Object result = null;
        try{
            result = proxy.invokeSuper(obj, args);
        }catch (Exception e){
            System.out.println("get ex:"+e.getMessage());
            throw e;
        }finally {
            System.out.println("after in cglib------洗碗");
        }
        return result;
    }
}

客户端调用

public class Client {
    public static void main(String[] args){
        Enhancer enhancer = new Enhancer();
        //真实对象(代理对象需要去继承这个对象)
        enhancer.setSuperclass(RealSubject.class);
        //设置回调方法,也就是我们需要植入的代码
        enhancer.setCallback(new DemoMethodInterceptor());
        //创建新的代理对象
        RealSubject subject = (RealSubject) enhancer.create();
        //执行代理对象的方法
        subject.work();
    }
}
相关文章
|
6月前
|
Java Spring 容器
SpringAop
SpringAop
55 0
|
XML 监控 Java
SpringAOP介绍与使用
SpringAOP介绍与使用
68 0
|
Java Spring
|
Java 数据库连接 数据库
SpringAOP(三)
SpringAOP(三)
|
数据安全/隐私保护
SpringAOP(二)
SpringAOP(二)
|
XML Java 数据格式
SpringAOP(一)
SpringAOP(一)
|
数据安全/隐私保护
SpringAOP(四)
SpringAOP(四)
|
XML 缓存 Java
|
缓存 监控 Java
SpringAop学习(一)
SpringAop学习(一)
88 0
SpringAop学习(一)
|
XML Java 数据安全/隐私保护
springAOP中的基本概念
springAOP中的基本概念
109 0
springAOP中的基本概念