6.Spring 动态代理(非注解)







这里,介绍两种非注解的动态代理:一种是JDK动态代理,使用的是java.lang.reflect

包中的InvocationHandler、Method和Proxy;另一种是CGlib动态代理:需要Spring

包中的,cglib-nodep.jar文件。






一.JDK动态代理


注意:JDK动态代理的对象,必须实现接口。


package com.zyy.service;

/**
 * Created by CaMnter on 2014/8/20.
 */
public interface PersonService_3 {

    public void save(String name);

    public void update(Integer personId, String name);

    public void delete(Integer personId);

}


package com.zyy.service.impl;

import com.zyy.service.PersonService_3;

/**
 * Created by CaMnter on 2014/8/21.
 */

/**
 * JDKProxyFactory 代理的对象 要求实现接口
 */

/*
 * 1.拦截所有的业务方法
 * 2.判断用户是否有权限
 * 3.有权限则允许他执行业务方法,没权限则不允许(这里根据user是否为null作为判断)
 */

public class PersonServiceBean_3 implements PersonService_3 {

    private String user = null;

    public String getUser() {
        return user;
    }

    public PersonServiceBean_3() {
    }

    public PersonServiceBean_3(String user) {

        this.user = user;

    }

    public void save(String name) {

        System.out.println("*****  save " + name + " *****");

    }

    public void update(Integer personId, String name) {

        System.out.println("*****  update  *****");

    }

    public void delete(Integer personId) {

        System.out.println("*****  delete  *****");

    }
}



package com.zyy.aop;

import com.zyy.service.impl.PersonServiceBean_3;

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

/**
 * Created by CaMnter on 2014/8/21.
 */

/**
 * JDK的动态代理
 * <p/>
 * 但是要求目标对象实现接口,因为
 * Proxy.newProxyInstance(this.targetObject.getClass().getClassLoader(),
 * this.targetObject.getClass().getInterfaces(), this);
 */

/*
 *
 * 当用户调用代理对象
 * 代理对象调用invoke
 * 判断权限(if)
 * 然后invoke方法中再委派给目标对象
 * (Object result = method.invoke(this.targetObject,args) ;)
 *
 */

public class JDKProxyFactory implements InvocationHandler {

    //代理的目标对象
    private Object targetObject;

    public Object createProxyInstance(Object targetObject) {

        this.targetObject = targetObject;

        /*
         * 第一个参数设置代码使用的类装载器,一般采用跟目标类相同的类装载器
         * 第二个参数设置代理类实现的接口
         * 第三个参数设置回调对象,当代理对象的方法被调用时,会委派给该参数指定对象的invoke方法
         */
        return Proxy.newProxyInstance(this.targetObject.getClass().getClassLoader(),
                this.targetObject.getClass().getInterfaces(), this);


    }

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

        PersonServiceBean_3 bean = (PersonServiceBean_3) this.targetObject;

        Object result = null;

        //权限过滤 代理对象有 user的值 才能调用它的方法
        if (bean.getUser() != null) {

            result = method.invoke(this.targetObject, args);

        }

        return result;
    }
}


junit4.4.测试代码:


    @Test
    public void jdkproxyTest() {

        //JDK动态代理

        JDKProxyFactory jdkProxyFactory = new JDKProxyFactory();

        System.out.println("*****  JDK动态代理  *****");

        System.out.println("*****  没有user值实例化目标  *****");

        PersonService_3 personService_3 = (PersonService_3) jdkProxyFactory.createProxyInstance(new PersonServiceBean_3());

        System.out.println("-----  无法调用方法  -----");

        personService_3.save("07");

        System.out.println("*****  有user值实例化目标  *****");

        personService_3 = (PersonService_3) jdkProxyFactory.createProxyInstance(new PersonServiceBean_3("CaMnter"));

        System.out.println("-----  可以调用方法  -----");

        personService_3.save("07");


    }


6.Spring 动态代理(非注解)_第1张图片



没有user值实例化目标,就在JDK代理那里过滤掉了,就无法使用方法。






二.CGlib动态代理


目标不需要接口,但是实现CBlib代理需要Spring 的依赖包cglib-nodep.jar


package com.zyy.service.impl;

/**
 * Created by CaMnter on 2014/8/21.
 */

/**
 * CGlibProxyFactory 代理的对象 不要求实现接口
 */

/*
 *
 * 1.拦截所有的业务方法
 * 2.判断用户是否有权限
 * 3.有权限则允许他执行业务方法,没权限则不允许(这里根据user是否为null作为判断)
 */

public class PersonServiceBean_4 {

    private String user = null;

    public String getUser() {
        return user;
    }

    public PersonServiceBean_4() {
    }

    public PersonServiceBean_4(String user) {

        this.user = user;

    }

    public void save(String name) {

        System.out.println("*****  save " + name + " *****");

    }

    public void update(Integer personId, String name) {

        System.out.println("*****  update  *****");

    }

    public void delete(Integer personId) {

        System.out.println("*****  delete  *****");

    }
}


package com.zyy.aop;

/**
 * Created by CaMnter on 2014/8/21.
 */

import com.zyy.service.impl.PersonServiceBean_4;

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

import java.lang.reflect.Method;

/**
 * CGllib的动态代理
 */

/*
 *
 * 当用户调用代理对象
 * 代理对象调用invoke
 * 判断权限(if)
 * 然后invoke方法中再委派给目标对象
 * (Object result = method.invoke(this.targetObject,args) ;)
 *
 */

public class CGlibProxyFactory implements MethodInterceptor {

    private Object targetObject;

    public Object createProxyInstance(Object targetObject) {

        this.targetObject = targetObject;

        //CGlib代理
        Enhancer enhancer = new Enhancer();

        //CGlib代理 就是继承了目标类 ,对目标类中所用非final 的进行覆盖
        enhancer.setSuperclass(this.targetObject.getClass());

        //当被目标类调用的时候
        enhancer.setCallback(this);


        return enhancer.create();


    }

    public Object intercept(Object o, Method method,
                            Object[] objects, MethodProxy methodProxy) throws Throwable {

        PersonServiceBean_4 bean = (PersonServiceBean_4) this.targetObject;

        Object result = null;

        //权限过滤 代理对象有 user的值 才能调用它的方法
        if (bean.getUser() != null) {

            result = method.invoke(this.targetObject, objects);

        }

        return result;

    }
}


junit4.4测试代码:


    @Test
    public void cglibproxyTest() {


        //CGlib动态代理

        CGlibProxyFactory cGlibProxyFactory = new CGlibProxyFactory();

        System.out.println("*****  CGlib动态代理  *****");

        System.out.println("*****  没有user值实例化目标  *****");

        PersonServiceBean_4 personServiceBean_4 = (PersonServiceBean_4) cGlibProxyFactory.createProxyInstance(new PersonServiceBean_4());

        System.out.println("-----  无法调用方法  -----");

        personServiceBean_4.save("07");

        System.out.println("*****  有user值实例化目标  *****");

        personServiceBean_4 = (PersonServiceBean_4) cGlibProxyFactory.createProxyInstance(new PersonServiceBean_4("CaMnter"));

        System.out.println("-----  可以调用方法  -----");

        personServiceBean_4.save("07");

    }


6.Spring 动态代理(非注解)_第2张图片




没有user值实例化目标,就在CGlib代理那里过滤掉了,就无法使用方法。








你可能感兴趣的:(6.Spring 动态代理(非注解))