Java与Spring的代理

1.静态代理

静态代理,顾名思义,手动代码代理。通过代理类实现被代理类的接口,进而完成代理过程。其实就是才能重写了,原本的接口方法,手动去在目标方法执行前中后,进行切割,进而实现代理。

public class TestStaticProxy {

    public static void main(String[] args) {
        IRegisterService iRegisterService = new RegisterServiceImpl();
        IRegisterService proxy = new RegisterServiceProxy(iRegisterService);
        proxy.register("RyanLee", "123");
    }
}
interface IRegisterService {
    void register(String name, String pwd);
}

class RegisterServiceImpl implements IRegisterService {
    @Override
    public void register(String name, String pwd) {
        System.out.println(String.format("【向数据库中插入数据】name:%s,pwd:%s", name, pwd));
    }
}

class RegisterServiceProxy implements IRegisterService {
    IRegisterService iRegisterService;

    public RegisterServiceProxy(IRegisterService iRegisterService) {
        this.iRegisterService = iRegisterService;
    }

    @Override
    public void register(String name, String pwd) {
        System.out.println("[Proxy]一些前置处理");
        System.out.println(“开始执行被代理的方法”);
        iRegisterService.register(name, pwd);
        System.out.println("[Proxy]一些后置处理");

    }
}

2.JDK代理

JDK代理,动态代理类和被代理类必须继承同一个接口。动态代理只能对接口中声明的方法进行代理,有一定限制。每一个动态代理实例都有一个关联的InvocationHandler。通过代理实例调用方法,方法调用请求会被转发给InvocationHandler的invoke方法。(这里就可以看出为啥在实例化代理类时,要传入目标类的接口,这样在代理类实现的invoke方法里可以直接执行接口方法实现了目标类被代理的过程)。实际上我们发现JDK的动态代理是基于反射的,而实现方式和静态代理很像,那为啥又说是动态代理呢?其实,细心的小伙伴就已经发现,JDK动态代理这种方式是一种对目标方法的增强,他不关心你目标方法,而是通过newProxyInstance方法来生成新的 的代理对象,只管代理执行,此处解耦。而对比静态代理就需要静态代理类知道目标类的信息,实现目标类的接口,限制很多。而动态代理在实现代理的时候,是传递需要代理类,的实现,无关接口 所以并不需要为每一种接口都写一个代理类了。

 public static void main(String[] args) {
        Target tar = new Target();
        ProxyHandler handler = new ProxyHandler();
        BBQ proxy = (BBQ) handler.getProxy(tar);
        proxy.sayBBQ("LF");
    }

    static class Target implements BBQ {
        @Override
        public void sayBBQ(String s) {
            System.out.println("这是原方法执行的 say bbq " + s);
        }
    }

    interface BBQ {
        void sayBBQ(String s);
    }

    static class ProxyHandler implements InvocationHandler {
        Object obj;

        public Object getProxy(Object obj) {
            this.obj = obj;
            Object o = Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), this);
            return o;
        }

        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            doBefore();
            Object result = method.invoke(obj, args);
            doAfter();
            return result;
        }

        private void doBefore() {
            Thread thread = Thread.currentThread();
            System.out.println("[Proxy]一些前置处理" + thread.getName() + " " + thread.getId());
        }

        private void doAfter() {
            System.out.println("[Proxy]一些后置处理");
        }
    }

3.cglib代理

JDK的动态代理机制只能代理实现了接口的类,而不能实现接口的类就不能实现JDK的动态代理,cglib是针对类来实现代理的,他的原理是对指定的目标类生成一个子类,并覆盖其中方法实现增强,但因为采用的是继承,所以不能对final修饰的类进行代理。

public static void main(String[] args) {
        Target tar = new Target();
        CGLIBProxyDemo handler = new CGLIBProxyDemo();
        Target proxy = (Target) handler.getProxy(tar);
        proxy.sayBBQ("cglib代理");
    }

    static class Target implements JDKProxyUtil.BBQ {
        @Override
        public void sayBBQ(String s) {
            System.out.println("这是原方法执行的 say bbq " + s);
        }
    }

    interface BBQ {
        void sayBBQ(String s);
    }

    static class CGLIBProxyDemo implements MethodInterceptor {
        private Object target;

        public Object getProxy(Object obj) {
            this.target = obj;
            Enhancer enhancer = new Enhancer();
            //生成子类
            enhancer.setSuperclass(this.target.getClass());
            // 回调方法
            enhancer.setCallback(this);
            // 创建代理对象
            return enhancer.create();
        }

        @Override
        public Object intercept(Object obj, Method method, Object[] param, MethodProxy methodProxy) throws Throwable {
            doBefore();
            Object result = methodProxy.invokeSuper(obj, param);
            doAfter();
            return result;
        }

        private void doBefore() {
            Thread thread = Thread.currentThread();
            System.out.println("[Proxy]一些前置处理" + thread.getName() + " " + thread.getId());
        }

        private void doAfter() {
            System.out.println("[Proxy]一些后置处理");
        }


    }

结语

仔细观察会发现:的原理依据,就是多态,要么实现接口生成代理类,要么继承目标类生成代理类,而的手段就是反射,利用反射来获取被代理类的信息,进而才能实现不需要了解目标信息来构建多态,从而动态解耦。

你可能感兴趣的:(Java与Spring的代理)