Java 动态代理的多种实现方式

一、动态代理简介

优势:在不修改源码的情况下,对目标方法进行相应的增强。

作用:完成程序功能之间的松耦合。

二、动态代理的多种实现

  • JDK代理:基于接口的动态代理技术(缺点,目标对象必须有接口,如果没有接口,则无法完成动态代理的实现)
  • cglib代理:基于父类的动态代理技术

两者的区别如图所示:

1. 基于JDK的实现

目标接口类:

public interface TargetInterface {
	public void save();

	public void print(String str);
}

目标类:

public class Target implements TargetInterface{

	public void save() {
		System.out.println("save running...");
	}

	public void print(String str) {
		System.out.println(str);
	}

}

增强类:

public class Advice {
	public void before() {
		System.out.println("前置增强");
	}

	public void after() {
		System.out.println("后置增强");
	}
}

测试类:

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

public class ProxyTest {

	public static void main(String[] args) {

		//目标对象
		final Target target = new Target();

		//增强对象
		final Advice advice = new Advice();

		TargetInterface proxyInstance = (TargetInterface)Proxy.newProxyInstance(
				target.getClass().getClassLoader(), 					//目标对象类加载器
				target.getClass().getInterfaces(), 						//目标对象相同的接口字节码对象数组
				new InvocationHandler() {
					//调用代理对象的任何方法,实质执行的都是invoke方法
					public Object invoke(Object proxy, Method method, Object[] args) throws Throwable{
						advice.before();								//前置增强
						Object invoke = method.invoke(target, args);	//执行目标方法
						advice.after();									//后置增强
						System.out.println();
						return invoke;
					}
				});

		//代理对象的方法测试
		proxyInstance.save();

		proxyInstance.print("JDK动态代理");
	}

}

运行截图:

2. 基于cglib的实现

需要导入Jar包,如果是maven项目,则在pom.xml文件加入如下配置:

<dependency>
	<groupId>org.springframework</groupId>
	<artifactId>spring-context</artifactId>
	<version>4.2.4.RELEASE</version>
</dependency>

目标类:

public class Target {
	public void save() {
		System.out.println("save running...");
	}

	public void print(String str) {
		System.out.println(str);
	}
}

增强类:

public class Advice {

	public void before() {
		System.out.println("前置增强");
	}

	public void after() {
		System.out.println("后置增强");
	}

}

测试类:

import java.lang.reflect.Method;

import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;

public class ProxyTest {

	public static void main(String[] args) {
		final Target target = new Target();
		final Advice advice = new Advice();

		//返回值就是动态生成的代理对象,基于cglib
		//创建增强器
		Enhancer enhancer = new Enhancer();

		//设置父类(目标)
		enhancer.setSuperclass(Target.class);

		//设置回调
		enhancer.setCallback(new MethodInterceptor() {
			public Object intercept(Object o, Method method, Object[] obj, MethodProxy methodProxy) throws Throwable{
				advice.before();
				Object invoke = method.invoke(target, obj);
				advice.after();
				System.out.println();
				return invoke;
			}
		});

		//创建代理对象
		Target proxy = (Target)enhancer.create();

		//测试代理方法
		proxy.save();
		proxy.print("基于cglib实现动态规划");

	}

}

运行截图:

三、为什么要有基于cglib的实现

使用JDK动态代理实现时,最大限制是被增强对象必须实现接口,并且增强的方法只能是接口中声明的方法。但在实际的项目中,可能总是存在对不实现业务接口的对象进行增强的需求,这时JDK动态代理将无能为力。

四、两种方式的适用场景

JDK动态代理

优点

  • 不依赖第三方jar包, 使用方便
  • 随着JDK的升级,JDK动态代理的性能在稳步提升

缺点

  • 只能代理实现了接口的类
  • 执行速度较慢

适用场景

  • 如果你的程序需要频繁、反复地创建代理对象,则JDK动态代理在性能上更占优。

cglib

优点

由于是动态生成字节码实现代理,因此代理对象的执行速度较快, 约为JDK动态代理的1.5 ~ 2倍
可以代理没有实现接口的对象

缺点

  • 不能代理final类
  • 动态生成字节码虽然执行较快,但是生成速度很慢,根据网上一些人的测试结果,cglib创建代理对象的速度要比JDK慢10 ~ 15倍。

适用场景

  • 不需要频繁创建代理对象的应用,如Spring中默认的单例bean,只需要在容器启动时生成一次代理对象。

以上就是Java 动态代理的多种实现方式的详细内容,更多关于Java 动态代理的实现的资料请关注我们其它相关文章!

(0)

相关推荐

  • 详解Java JDK动态代理

    今天来看看Java的另一种代理方式--JDK动态代理 我们之前所介绍的代理方式叫静态代理,也就是静态的生成代理对象,而动态代理则是在运行时创建代理对象.动态代理有更强大的拦截请求功能,因为可以获得类的运行时信息,可以根据运行时信息来获得更为强大的执(骚)行(操)力(作). 我们还是以上一个例子为例,这里的IStars接口和Stars类都不需要修改,只需要修改代理类. 创建JDK动态代理需要先实现InvocationHandler接口,并重写其中的invoke方法,具体步骤如下: 1. 创建一个类

  • Java简单实现动态代理模式过程解析

    基本知识:JDK动态代理是java.lang.reflect.*包提供的方式,它必须借助一个接口才能生成代理对象. 步骤: 1.首先建一个接口类,并提供一个实现类: public interface ISubject { public int add(int a, int b); } public class Subject implements ISubject { @Override public int add(int a, int b) { return a + b; } } 2.创建一

  • JAVA使用动态代理对象进行敏感字过滤代码实例

    这篇文章主要介绍了JAVA使用动态代理对象进行敏感字过滤代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 package com.hopetesting.web.filter; import javax.servlet.*; import javax.servlet.annotation.WebFilter; import java.io.BufferedReader; import java.io.FileNotFoundExcepti

  • Java动态代理静态代理实例分析

    代理模式:为其他对象提供一种代理以控制某个对象的访问.用在:在某些情况下,一个客户不想或者不能直接访问另一个对象,而代理对象可以在客户端和目标对象之前起到中介的作用,代理对象还可以完成它附加的操作. 例子:就像房东.租客.中介的关系.中介(代理对象)为房东(真实对象)出租房子,租客(客户)通过中介(代理对象)来找房子租房子,中介完成了租房以后可以收取中介费(附加操作). 先看看静态代理模式,通过上面对代理模式的理解,可以了解到代理模式:即不直接通过new一个真实对象来调用方法,而是通过代理对象来

  • Java JDK动态代理实现原理实例解析

    JDK动态代理实现原理 动态代理机制 通过实现 InvocationHandler 接口创建自己的调用处理器 通过为 Proxy 类指定 ClassLoader 对象和一组 interface 来创建动态代理类 通过反射机制获得动态代理类的构造函数,其唯一参数类型是调用处理器接口类型 通过构造函数创建动态代理类实例,构造时调用处理器对象作为参数被传入 Interface InvocationHandler 该接口中仅定义了一个方法Object:invoke(Object obj,Method m

  • Java两种方式实现动态代理

    一.JDK动态代理 Java 在 java.lang.reflect 包中有自己的代理支持,该类(Proxy.java)用于动态生成代理类,只需传入目标接口.目标接口的类加载器以及 InvocationHandler 便可为目标接口生成代理类及代理对象.我们称这个Java技术为:动态代理 @CallerSensitive public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, Invoca

  • Java动态代理语法Proxy类原理详解

    1.前言 写动态代理的代码涉及了一个非常重要的类 Proxy,通过Proxy的静态方法newProxyInstance才会动态创建代理对象. 2.newProxyInstance方法 public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) 三个参数分别表示: loader表示类加载器, interfaces表示代码要用来代理的接口 , h表示一个

  • Java JDK动态代理(AOP)用法及实现原理详解

    Java-JDK动态代理(AOP)使用及实现原理分析 第一章:代理的介绍 介绍:我们需要掌握的程度 动态代理(理解) 基于反射机制 掌握的程度: 1.什么是动态代理? 2.动态代理能够做什么? 后面我们在用Spirng和Mybatis的时候,要理解怎么使用的. 1.什么是代理? 代理,在我们日常生活之中就有体现,代购,中介,换ip,商家等等. 比如有一家美国的大学,可以对全世界招生.留学中介(代理 ) 留学中介(代理):帮助这家美国的学校招生,中介是学校的代理中介是代替学校完成招生功能 代理特点

  • Java代理模式实例详解【静态代理与动态代理】

    本文实例讲述了Java代理模式.分享给大家供大家参考,具体如下: 即Proxy Pattern,23种java常用设计模式之一.代理模式的定义:对其他对象提供一种代理以控制对这个对象的访问. Java的代理模式是Java中比较常用的设计模式,分为2中代理:静态代理与动态代理(JDK动态代理和cglib动态代理) 优点: 职责清晰 真实角色只需关注业务逻辑的实现,非业务逻辑部分,后期通过代理类完成即可. 高扩展性 不管真实角色如何变化,由于接口是固定的,代理类无需做任何改动. 缺点: 很明显的一点

  • 详细分析java 动态代理

    1.动态代理的特点: 字节码随用随创建,随用随加载 2.作用: 不修改源码的基础上对源码进行加强 3.分类: (1)基于接口的动态代理: 涉及到的类:Proxy,由JDK官方提供,使用Proxy类中的newProxyInstance方法创建对象.创建代理对象时要求被代理对象至少实现一个接口,否则无法使用 参数: ClassLoader:类加载器,他是用于加载对象字节码的,和被代理对象使用相同的类加载器,为固定写法 class[]:字节码数组,他是用于让代理对象和被代理对象具有相同的方法,也是固定

  • 详解Java Cglib动态代理

    今天来介绍另一种更为强大的代理--Cglib动态代理. 什么是Cglib动态代理? 我们先回顾一下上一篇的jdk动态代理,jdk动态代理是通过接口来在运行时动态创建委托类的代理对象,但是跟静态代理一样有一个缺点,就是必须和委托类实现相同的接口,当接口数量增加时,便需要增加代理类的数量才能满足需求,而且如果委托类是别人写的,而且没有实现任何接口,那么jdk动态代理就有些力不从心了. 这时候Cglib动态代理就脱颖而出了,Cglib并不依赖接口,可以直接生成委托类的代理对象,而且可以代理委托类的任意

随机推荐