精华内容
下载资源
问答
  • java动态代理

    万次阅读 2020-12-14 17:59:02
    最近在看一些技术源码的时候,发现很多地方都是动态代理, 真可谓是一切皆代理啊,所以我们需要弄明白代理模式这样在看源码的时候会好受很多。 2、基本概念 代理(Proxy)模式提供了间接访问目标对象的方式,即通过...

    1、引言

    最近在看一些技术源码的时候,发现很多地方都是动态代理, 真可谓是一切皆代理啊,所以我们需要弄明白代理模式这样在看源码的时候会好受很多。

    2、基本概念

    代理(Proxy)模式提供了间接访问目标对象的方式,即通过代理对象访问目标对象,这样做的好处是:可以在目标对象的功能上,增加额外的功能补充,即扩展目标对象的功能。

    这就符合了设计模式低开闭原则,即在对既有代码不改动的情况下进行功能扩展。

    举个我们平常非常常见的例子, 明星和经纪人就是被代理和代理的关系,明细出演活动的时候,明细就是一个目标对象,他只负责活动中的节目,而其他的琐碎的事情就交给他的代理人(经纪人)来解决。这就是代理思想 中的一个例子。

    3、静态代理

    静态代理的特点:代理类和目标类必须实现 同一个接口或者继承相同的父类。所以我们需要 定义一个接口。下面来看具体实现demo。

    接口类:

    /**
     * @author zhenghao
     * @description:
     * @date 2020/12/1410:28
     */
    public interface Istart {
    
        void sing();
    }

    目标类:

    /**
     * @author zhenghao
     * @description:
     * @date 2020/12/1416:07
     */
    public class LDHStar implements Istart {
    
        @Override
        public void sing() {
            System.out.println("华仔唱歌");
        }
    }
    

    代理类:

    /**
     * @author zhenghao
     * @description:
     * @date 2020/12/1416:08
     */
    public class StaticPorxyManager implements Istart {
    
        private Istart target;
        public StaticPorxyManager(Istart target) {
            this.target = target;
        }
    
        @Override
        public void sing() {
            System.out.println("演唱会之前。。。。");
            this.target.sing();
            System.out.println("演唱会之后。。。。");
    
        }
    }

    测试类:

    /**
     * @author zhenghao
     * @description:
     * @date 2020/12/1410:46
     */
    public class StaticTeasMain {
    
        public static void main(String[] args) {
            Istart ldhStar = new LDHStar();
    
            StaticPorxyManager staticPorxyManager = new StaticPorxyManager(ldhStar);
            staticPorxyManager.sing();
    
        }
    }

    静态代理类优缺点:

    有点:可以在不修改目标代码的情况下,扩折额外 功能

    缺点:因为代理类和目标类必须实现相同的接口,所以会有很多代理类,类太多, 同时,一旦接口增加方法,目标对象很代理对象都需要维护。而动态代理可以解决上面的问题。

    4、JDK动态代理

    动态代理的主要特点就是能够在程序运行时JVM才为目标对象生成代理对象。

    常说的动态代理也叫做JDK 代理也是一种接口代理,之所以叫做接口代理,是因为被代理的对象也就是目标对象必须实现至少一个接口,没有实现接口不能使用这种方式生成代理对象,JDK中生成代理对象的代理类就是Proxy,所在包是java.lang.reflect.

    接口:

    /**
     * @author zhenghao
     * @description:
     * @date 2020/12/1410:28
     */
    public interface Istart {
    
        void sing();
    }
    

    目标类:

    /**
     * @author zhenghao
     * @description:
     * @date 2020/12/1410:29
     */
    public class WangFengStar implements Istart {
        @Override
        public void sing() {
            System.out.println("汪峰唱歌。。。");
        }
    }
    
    InvocationHandler类:
    import java.lang.annotation.Target;
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    
    /**
     * @author zhenghao
     * @description:
     * @date 2020/12/1410:32
     */
    public class StarInvocationHandler implements InvocationHandler {
    
        private  Object target;
        public StarInvocationHandler(Object target) {
            this.target = target;
        }
    
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    
            System.out.println("演唱会前工作");
            //调用目标对象的目标方法
            method.invoke(target,args);
            System.out.println("演唱会后工作");
            return null;
        }
    }
    

    代理工厂:

    import java.lang.reflect.Proxy;
    
    /**
     * @author zhenghao
     * @description:
     * @date 2020/12/1410:30
     */
    public class ProxyFactory {
    
        private Object target;
        private StarInvocationHandler starInvocationHandler;
        public ProxyFactory( Object target) {
            this.target = target;
            this.starInvocationHandler = new StarInvocationHandler(target);
        }
    
        public Object getProxyObject(){
           return Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(),starInvocationHandler);
        }
    }

    测试方法:

    public class TeasMain {
    
        public static void main(String[] args) {
            Istart wangfengStar = new WangFengStar();
            Istart proxyObject = (Istart)new ProxyFactory(wangfengStar).getProxyObject();
            proxyObject.sing();
        }
    }

    JDK代理方式不需要代理对象实现接口,但是目标对象一定要实现接口,但是我们在项目中有很多需要代理的类并没有实现接口,所以这也算是这种代理方式的一种缺陷。

    5、cglib动态代理

    如果我们 需要给没有是实现任何接口的目标类生成代理对象,JDK方式是做不到的。这是就可以使用继承目标类以目标对象子类的方式实现代理,这种方法就叫做Cglib代理,也叫做子类代理,他是在内存中构建一个子类对象从而 实现对目标对象功能的扩展。

    Cglib是一个强大的高性能代码生成包,他可以在运行期扩展java类和扩展java接口。它广泛的被许多AOP框架使用,例如Sring AOP和synaop,为他们提供方法的intercepion(拦截)

    Cglib包的底层是通过使用一个小而快的字节码处理框架ASM来转换字节码并生成新的类。

    Cglib子类代理实现方法:

    1.需要引入cglib的jar文件 cglib-2.2.2.jar asm-3.3.1.jar,但是Spring的核心包中已经包括了Cglib功能,所以直接引入spring-core-3.2.5.jar即可.
    2.引入功能包后,就可以在内存中动态构建子类
    3.代理的类不能为final,否则报错
    4.目标对象的方法如果为final/static,那么就不会被拦截,即不会执行目标对象额外的业务方法.

    目标类:

    /**
     * @author zhenghao
     * @description:
     * @date 2020/12/1410:57
     */
    public class JieLunStar {
    
        public void sing(){
            System.out.println("杰伦唱歌");
        }
    }

    代理工厂:

    import org.springframework.cglib.proxy.Enhancer;
    import org.springframework.cglib.proxy.MethodInterceptor;
    import org.springframework.cglib.proxy.MethodProxy;
    
    import java.lang.reflect.Method;
    
    /**
     * @author zhenghao
     * @description:
     * @date 2020/12/1410:58
     */
    public class CglibProxyFactory implements MethodInterceptor {
    
        //维护目标对象
        private Object target;
    
        public CglibProxyFactory(Object target) {
            this.target = target;
        }
    
        /**
         * @Description:获得目标类的代理对象
         * @author: zhenghao
         * @date: 2020/12/14 11:02
        */
        public Object getProxyObject(){
            //1、工具类
            Enhancer enhancer = new Enhancer();
            //2、设置父类
            enhancer.setSuperclass(target.getClass());
            //3、设置回调
            enhancer.setCallback(this);
            //4、创建代理类
            Object proxyObject = enhancer.create();
            return proxyObject;
    
        }
    
        @Override
        public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
    
            System.out.println("演唱会前工作");
            //执行目标对象的目标方法
            method.invoke(target,objects);
            System.out.println("演唱后前工作");
            return null;
        }

    测试类:

    /**
     * @author zhenghao
     * @description:
     * @date 2020/12/1410:46
     */
    public class CglibTeasMain {
    
        public static void main(String[] args) {
            JieLunStar jieLunStar = new JieLunStar();
            JieLunStar proxyObject = (JieLunStar)new CglibProxyFactory(jieLunStar).getProxyObject();
            proxyObject.sing();
        }
    }
    

    到这三种代理方式我们都介绍完了,下面总结一下:

    1、如果目标对象实现了接口,我们就采用JDK方式实现动态代理

    2、如果目标对象没有实现接口,我们就需要采用cglib方式实现动态代理;

    6、目标是接口+注解的动态代理

    注解类:

    /**
     * @author zhenghao
     * @description:
     * @date 2020/12/1411:33
     */
    @Target(ElementType.METHOD)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface Select {
    
        String value() default "";
    }

    目标类:

    /**
     * @author zhenghao
     * @description:
     * @date 2020/12/1411:32
     */
    public interface IUserDao {
    
        @Select("select * from user")
        String getUser();
    
      
    }
    InvocationHandler类:
    /**
     * @author zhenghao
     * @description:
     * @date 2020/12/1410:32
     */
    public class UserInvocationHandler implements InvocationHandler {
    
    
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            //创建类的是一个具体的实现类
            if (Object.class.equals(method.getDeclaringClass())){
                return method.invoke(this,args);
            }else {
                //得到所有注解
                String value = method.getAnnotation(Select.class).value();
                System.out.println("接口上面的注解的内容:" + value);
    
                //实现具体的业务逻辑 如远程http调用实现等
                return "user info";
            }
    
        }
    }
    

    代理工厂:

    import java.lang.reflect.Proxy;
    
    /**
     * @author zhenghao
     * @description:
     * @date 2020/12/1411:47
     */
    public class InterfaceProxyFactory  {
    
        private  Class<?> target;
        private UserInvocationHandler userInvocationHandler;
        public InterfaceProxyFactory( Class<?> target) {
            this.target = target;
            this.userInvocationHandler = new UserInvocationHandler();
        }
    
        public Object getProxyObject(){
            return Proxy.newProxyInstance(target.getClassLoader(),new  Class[]{target},userInvocationHandler);
        }
    }

    测试类:

    /**
     * @author zhenghao
     * @description:
     * @date 2020/12/1410:46
     */
    public class InterfaceProxyTeasMain {
    
        public static void main(String[] args) {
            IUserDao proxyObject = (IUserDao) new InterfaceProxyFactory(IUserDao.class).getProxyObject();
            System.out.println(proxyObject.getUser());
        }
    }

     

    展开全文
  • java 动态代理

    千次阅读 2016-08-29 09:54:45
    java 动态代理

    个人理解:

    动态代理是面向接口执行的,他是根据java的反射机制动态生成的。

    1,首先,有一个类,类中有执行 的方法。

    public interface Count {
    	public void queryCount();
    	public void updateCount();
    }
    
    2,然后有一个实现类,去实现接口

    public class CountImpl implements Count {
    
    	@Override
    	public void queryCount() {
    		System.out.println("query...");
    
    	}
    
    	@Override
    	public void updateCount() {
    		System.out.println("update...");
    	}
    
    }

    3,写一个代理处理器类

    public class CountProxy implements InvocationHandler{
    	
    	private Object  target;  //被代理的对象
    	
    	public Object getTarget() {
    		return target;
    	}
    
    	public void setTarget(Object target) {  //set方法可以直接将对象set近要执行代理的方法
    		this.target = target;
    	}
    
    	public void before(Method method){   //执行 代码 之前的方法
    		System.out.println(method.getName() + "  start !");
    	}
    	
    	public void after(Method method){   //执行 代码 之后的方法
    		System.out.println(method.getName() + "  end !");
    	}
    
    	@Override
    	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    		//proxy 产生代理              method 方法               args 参数
    		before(method);
    		method.invoke(target, args);  //target  被代理对象
    		after(method);
    		return null;
    	}
    
    	
    }
    4,执行方法

    public class TestCount {
    
    	public static void main(String[] args) {
    		Count count = new CountImpl();  //产生被代理对象
    		CountProxy proxy = new CountProxy();   
    		proxy.setTarget(count); // 设置被代理对象
    		Count countProxy = (Count) Proxy.newProxyInstance(Count.class.getClassLoader(), count.getClass().getInterfaces(), proxy);
    		//产生代理     Count.class.getClassLoader() 被代理对象的ClassLoader()   
    		//count.getClass().getInterfaces()  产生被代理对象实现的接口 
    		//proxy 用的InvocationHandler处理方式;
    		countProxy.queryCount();
    		countProxy.updateCount();
    	}
    }
    



    展开全文
  • Java 动态代理

    2015-05-17 22:23:28
  • JAVA动态代理

    2017-05-27 16:49:13
    JAVA动态代理 因为现在在在学java的一些框架技术,比如ssh,mybatis等,总是提到动态代理,而且用到的还蛮多的,因此将jdk动态代理好好研究一下。 代理模式 代理模式是java中一种常见的设计模式,他的特征是代理类...

    因为现在在在学java的一些框架技术,比如ssh,mybatis等,总是提到动态代理,而且用到的还蛮多的,因此将jdk动态代理好好研究一下。

    代理模式
    代理模式是java中一种常见的设计模式,他的特征是代理类和委托类实现相同的接口。代理类主要负责为委托类预处理消息、过滤消息、把消息转发给委托类,以及事后处理消息等。java动态代理的出现,使我们不需要手动写代理类,只需要提供一组接口和委托类对象,即可动态生成代理类。

    CGLIB动态代理

    CGLIB代理是针对类实现代理,主要是指定的类生成一个子类,覆盖其中的所有方法,所有该类或方法不能声明称final的。

    JDK动态代理

    代理对象和目标对象实现了相同的接口,目标对象作为代理代理对象的一个属性,可以在调用目标对象响应方法前后加上其他业务的逻辑。JDK动态代理只能针对实现了接口的类生成代理。

    CGLIB测试代码:

    定义一个实现MethodInterceptor的方法:

    
    package com.jcw.proxy;
    
    import net.sf.cglib.proxy.Enhancer;
    import net.sf.cglib.proxy.MethodInterceptor;
    import net.sf.cglib.proxy.MethodProxy;
    import java.lang.reflect.Method;
    public class DynamicProxyByCGLib implements MethodInterceptor {
    
    
    private Object target;
    
    public DynamicProxyByCGLib(Object target) {
        this.target = target;
    }
    
    public Object getInstance() {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(this.target.getClass());
        enhancer.setCallback(this);
        return enhancer.create();
    }
    
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println("before intercept");
        methodProxy.invokeSuper(o, objects);
        System.out.println("after interept");
        return null;
    }
    

    }

    定义一个测试类:

    
    package com.jcw.proxy;
    public class CGLIBProxyTest {
        public void say() {
            System.out.println("say for CGLIBProxyTest");
        }
        public static void main(String[] args) {
            CGLIBProxyTest cglibProxyTest = new CGLIBProxyTest();
            DynamicProxyByCGLib dynamicProxyByCGLib = new DynamicProxyByCGLib(cglibProxyTest);
            CGLIBProxyTest cglibProxyTest1 = (CGLIBProxyTest) dynamicProxyByCGLib.getInstance();
            cglibProxyTest1.say();
        }
    }
    
    

    JDK测试代码:

    定义一个接口:
    
    package com.jcw.proxy;
    public interface JdkInterfaces1 {
        void say();
    }
    
    定义一个实现InvocationHandler接口的类:
    
    package com.jcw.proxy;
    
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    import java.util.Arrays;
    public class DynamicProxyByJDK implements InvocationHandler {
        private Object target;
    
    
    public DynamicProxyByJDK(Object target) {
        this.target = target;
    }
    
    public Object getInstance() {
        System.out.println("classLoader:" + target.getClass().getClassLoader());
        System.out.println("interfaces:" + Arrays.toString(target.getClass().getInterfaces()));
        return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
    }
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("before invoke");
        method.invoke(target, args);
        System.out.println("after invoke");
        return null;
    }
    

    }

    jdk测试的类

    
    package com.jcw.proxy;
    public class JdkProxyTest implements JdkInterfaces1{
    
    
    public void say() {
        System.out.println("say for JdkProxyTest");
    }
    
    public static void main(String[]  args) {
        JdkProxyTest jdkProxyTest = new JdkProxyTest();
        DynamicProxyByJDK dynamicProxyByJDK = new DynamicProxyByJDK(jdkProxyTest);
        JdkInterfaces1 jdkProxyTest1 = (JdkInterfaces1) dynamicProxyByJDK.getInstance();
        jdkProxyTest1.say();
    }
    

    }

    总结:CGLIB主要是针对类实现代理,主要通过根据指定的类生成一个代理类,覆盖其中的方法。当然对于实现接口的类,CGLIB同样可以实现。
    JDK动态代理只能对实现了接口的类生成代理,而不是针对类。

    展开全文
  • Java动态代理

    2016-04-16 11:08:55
    之前在看java class的放射机制。通过反射机制可以实现java类的动态代理。我们都熟知代理模式,jdk中有...例如Spring框架就是建立在java动态代理机制之上的,充分的应用java动态代理将使程序变得更加灵活。 下面我们

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 23,770
精华内容 9,508
关键字:

java动态代理

java 订阅