Java 代理详解
Java的世界,框架永远如夜空繁星Java的框架,多如牛毛Spring ,hibernate,ibatis/myBatis, struts1/2, shiro, lucene等等,有时候会觉得这些框架都非常神奇,解决了很多开发的问题,让开发人员进行系统、服务开发时变得简单,框架内部变得神秘,其实无论什么框架,其实现无非是基于JDK来开发的,反射、代理、泛型、注解、以及各种设计模式是框架的灵魂。比如下图的代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
|
protected Object createProxy(
Class<?> beanClass, String beanName, Object[] specificInterceptors, TargetSource targetSource) {
ProxyFactory proxyFactory = new ProxyFactory();
// Copy our properties (proxyTargetClass etc) inherited from ProxyConfig.
proxyFactory.copyFrom( this );
if (!shouldProxyTargetClass(beanClass, beanName)) {
// Must allow for introductions; can't just set interfaces to
// the target's interfaces only.
Class<?>[] targetInterfaces = ClassUtils.getAllInterfacesForClass(beanClass, this .proxyClassLoader);
for (Class<?> targetInterface : targetInterfaces) {
proxyFactory.addInterface(targetInterface);
}
}
Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
for (Advisor advisor : advisors) {
proxyFactory.addAdvisor(advisor);
}
proxyFactory.setTargetSource(targetSource);
customizeProxyFactory(proxyFactory);
proxyFactory.setFrozen( this .freezeProxy);
if (advisorsPreFiltered()) {
proxyFactory.setPreFiltered( true );
}
return proxyFactory.getProxy( this .proxyClassLoader);
} |
用的正好是反射机制和代理模式,本文主要讲讲Java的代理模式的思想,以及他的分类和实现方式。
-
静态代理
静态代理是代理最简单的一种方式,实现为,一个实现类,一个接口,一个代理类,一个测试类,即可完成静态代 理,举个“栗子”,我们去银行存钱我们没有存钱的能力,需要漂亮的营业员小姐(可能是娘炮的先生)帮我们把钱存到账户里面,我们实际是代理,真正的实现类是营业员小姐,我们在存钱时需要先给钱给营业员,而钱不会自己跑到营业员小姐那里,所以我们是代理类。代码如下
银行员工接口
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
/** *
*/
package cn.inspries.test.proxy;
/* 银行美女 * ***********************************
* @author sandy
* @project cn.inspries.test.proxy
* @create_date 2014-8-14 下午9:07:32
* ***********************************
*/
public class BankBeauty implements MoneyManager{
@Override public void putMoney( double money) {
System.out.println( "您存了" + money + "元人民币,请对我的服务进行评价!" );
} } |
客户类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
/** *
*/
package cn.inspries.test.proxy;
/* * ***********************************
* @author sandy
* @project cn.inspries.test.proxy
* @create_date 2014-8-14 下午9:06:50
* ***********************************
*/
public class Custom implements MoneyManager{
BankBeauty bankBeauty = new BankBeauty();
@Override public void putMoney( double money) {
System.out.println( "去到银行柜台!开始存钱" );
bankBeauty.putMoney(money); System.out.println( "存好了" );
} } |
静态代理接口代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
/** *
*/
package cn.inspries.test.proxy;
/* * ***********************************
* @author sandy
* @project cn.inspries.test.proxy
* @create_date 2014-8-14 下午9:08:54
* ***********************************
*/
public interface MoneyManager {
void putMoney( double money);
} |
静态代理测试类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
/** *
*/
package cn.inspries.test.proxy;
/* * ***********************************
* @author sandy
* @project cn.inspries.test.proxy
* @create_date 2014-8-14 下午9:26:41
* ***********************************
*/
public class Test {
public static void main(String[] args) {
Custom custom = new Custom();
custom.putMoney( 200.0 );
} } |
输出结果:
去到银行柜台!开始存钱
您存了200.0元人民币,请对我的服务进行评价!
存好了
上面的例子很简单这里就不再多做解释了
-
动态代理
接口和实现类跟静态代理一样,代理类有所区别。代理类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
|
/** *
*/
package cn.inspries.test.proxy.dynic;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/* * ***********************************
* @author sandy
* @project cn.inspries.test.proxy
* @create_date 2014-8-14 下午9:06:50
* ***********************************
*/
public class DynicProxy implements InvocationHandler {
Object targetObject;
public Object newProxyInstance(Object targetObject) {
this .targetObject = targetObject;
return Proxy.newProxyInstance(targetObject.getClass().getClassLoader(),
targetObject.getClass().getInterfaces(), this );
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
Object returnObject = null ;
try {
System.out.println( "调用动态代理方法了!" );
returnObject = method.invoke(targetObject, args);
} catch (Exception e) {
e.printStackTrace();
throw e;
}
return returnObject;
}
} |
JDK动态代理测试类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
/**
*
*/
package cn.inspries.test.proxy.dynic;
import cn.inspries.test.proxy.BankBeauty;
import cn.inspries.test.proxy.MoneyManager;
/* * ***********************************
* @author sandy
* @project cn.inspries.test.proxy
* @create_date 2014-8-14 下午9:26:41
* ***********************************
*/
public class DynicTest {
public static void main(String[] args) {
DynicProxy dynicProxy = new DynicProxy();
MoneyManager moneyManager = (MoneyManager) dynicProxy.newProxyInstance( new BankBeauty());
moneyManager.putMoney( 2000 );
} } |
输出
调用代理方法了!
您存了2000.0元人民币,请对我的服务进行评价!
-
Cglib动态代理,JDK动态代理的局限是,被代理的服务类必须实现接口,否则无法使用代理,将会报错,而Spring里面很多地方用的是类,他是通过Cglib来完成无接口的动态代理的。代码也比较简洁如下。
Cglib动态代理类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
/** *
*/
package cn.inspries.test.proxy.dynic_cglib;
import java.lang.reflect.Method;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
/* * ***********************************
* @author sandy
* @project cn.inspries.test.proxy
* @create_date 2014-8-14 下午9:06:50
* ***********************************
*/
public class CglibDynicProxy implements MethodInterceptor {
Object targetObject; public Object newProxyInstance(Object targetObject) {
this .targetObject = targetObject;
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass( this .targetObject.getClass());
enhancer.setCallback( this ); // call back method
return enhancer.create(); // create proxy instance
} @Override public Object intercept(Object target, Method method, Object[] args,
MethodProxy proxy) throws Throwable {
System.out.println( "使用cglib的MethodInterceptor.intercept方法调用代理了!" );
Object result = proxy.invokeSuper(target, args); System.out.println( "方法走完了,哈哈" );
return result;
} } |
Cglib测试类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
/** *
*/
package cn.inspries.test.proxy.dynic_cglib;
import cn.inspries.test.proxy.BankBeauty;
import cn.inspries.test.proxy.MoneyManager;
/* * ***********************************
* @author sandy
* @project cn.inspries.test.proxy
* @create_date 2014-8-14 下午9:26:41
* ***********************************
*/
public class DynicTest {
public static void main(String[] args) {
CglibDynicProxy cglibDynicProxy = new CglibDynicProxy();
MoneyManager manager = (MoneyManager) cglibDynicProxy.newProxyInstance( new BankBeauty());
manager.putMoney( 1688 );
} } |
程序输出:
使用cglib的MethodInterceptor.intercept方法调用代理了!
您存了1688.0元人民币,请对我的服务进行评价!
方法走完了,哈哈
总结:动态代理和静态代理的区别
1、静态代理由程序员创建或工具生成代理类的源码,再编译代理类。所谓静态也就是在程序运行前就已经存在代理类的class文件,代理类和委托类的关系在运行前就确定了。
2、静态代理只服务于一个接口。而动态代理可以服务于多个接口。
3、静态代理中如果接口增加一个方法,除了所有实现类需要实现这个方法外,所有代理类也需要实现此方法。增加了代码维护的复杂度。
4、动态代理类的代码是在程序运行期间由JVM根据反射等机制动态的生成,不存在代理类的字节码文件。代理类和委托类的关系在程序运行时候确定。
5、动态代理与普通的代理相比较,最大的好处是接口中声明的所有方法都被转移到一个集中的方法中处理(invoke),这样,在接口方法数量比较多的时候,我们可以进行灵活处理,而不需要像静态代理那样每一个方法进行中转。
而JDK动态代理方式和CGlib区别是,使用jdk代理是,代理类必须实现接口,而Cglib不论有没有接口都可以实现,所以cglib局限较小。
相关推荐
更好的了解java动态代理的原理!
JDK 动态代理JDK 提供了 java.lang.reflect.Proxy 类和 java.lang.reflect.InvocationHandler 接口来支持动态代理。Proxy 类用于创建一个代理对象,而 InvocationHandler 接口则定义了代理对象的方法调用处理逻辑。...
Java代理机制是Java编程中一个重要的特性,它允许我们在不修改原有代码的基础上,为已有类增加额外的功能。本文将深入探讨两种主要的Java代理实现:JDK动态代理和CGLIB代理。 一、JDK动态代理 JDK动态代理基于接口...
代理模式是我们比较常用的设计模式之一。其中新思想是为了提供额外的处理或者不同的操作而在实际对象与调用者之间插入一个代理对象。这些额外的操作通常需要与实际对象进行通信,代理模式一般涉及到的角色有: ...
031505_【第15章:Java反射机制】_动态代理笔记.pdf 031506_【第15章:Java反射机制】_工厂设计模式笔记.pdf 031601_【第16章:Annotation】_系统内建Annotation笔记.pdf 031602_【第16章:Annotation】_自定义...
Java 动态代理详解(代理模式+静态代理+JDK动态代理+CGLIB动态代理) Java 动态代理是 Java 编程语言中的一种强大工具,广泛应用于 Spring AOP、Hibernate 数据查询、测试框架的后端 mock、RPC 远程调用、Java 注解...
总结一下,Java代理模式的核心在于`Proxy`类和`InvocationHandler`接口,它们共同实现了在运行时动态创建符合特定接口的代理对象。通过代理,我们可以在不修改原始对象代码的情况下,添加额外的功能或者控制对原始...
Java类库是Java编程语言的核心组成部分,它提供了一系列预先定义的类和接口,开发者可以使用这些类和接口来实现各种功能,从而简化编程工作。...这份"java类库详解(PDF版)"文档将是你深入理解Java类库的重要参考资料。
Java 动态代理详解与 CGLib 实现 在 Java 中,代理模式是一种设计模式,它允许我们在不修改原有对象的基础上,为对象增加额外的功能。代理模式的核心在于代理类(Proxy)作为真实对象(RealSubject)的替代品,提供...
Java动态代理机制是一种在运行时创建代理类和代理对象的技术,它允许我们在不修改源代码的情况下,对已有的接口或类进行扩展,增加新的功能。动态代理主要应用于事件监听、事务处理、性能监控等场景,提供了更加灵活...
Java 动态代理是Java平台提供的一种强大的工具,它允许我们在运行时动态生成代理类,这些代理类可以实现一组指定的接口,同时还能在方法调用前后添加自定义的行为。这种机制大大简化了面向切面编程(AOP)和事件监听...
最后,本书可能还会涉及Java的最新特性,比如注解、泛型、枚举、动态代理等,这些都是Java语言不断演进的体现,有助于开发者保持与时俱进。 通过阅读《Java2编程详解》,无论是初学者还是有经验的开发者,都能从中...
### Java代理模式与Java动态代理详解 #### 一、代理模式概述 代理模式是一种软件设计模式,它在客户端和目标对象之间提供了一种间接层。这种模式的主要目的是控制客户端对目标对象的访问,并且可以在不修改原有...
10. **Java高级特性**:包括反射、动态代理、注解、枚举、集合工厂方法、泛型等,这些都是Java2平台的进阶特性,它们极大地增强了Java的灵活性和可维护性。 通过阅读《Java2编程详解》,读者可以系统地学习和掌握...
Java中的代理模式是一种设计模式,它允许我们创建一个代理对象,该对象可以在调用实际对象的方法之前或之后执行额外的操作,而无需修改原始代码。在Java中,代理主要分为静态代理和动态代理。 1. 静态代理: 静态...
Java动态代理机制详解_动力节点Java学院整理,动力节点口口相传的Java黄埔军校
Java动态代理技术是Java编程中一个非常重要的特性,它允许我们在运行时动态创建具有特定行为的对象。这种技术常用于AOP(面向切面编程)和框架中,如Spring AOP,用于实现方法拦截、事务管理等功能。Java提供了两种...
- `动态代理详解.docx`则可能深入讨论了Java动态代理的细节,包括实际应用场景和常见问题。 以上内容是对Java动态代理技术的概述,详细的学习和理解可以通过阅读给定的文档来深入探讨。在实践中,掌握动态代理能够...
JDK 动态代理技术详解 JDK 动态代理技术是 Java 语言自身对动态代理的支持,类似于 JDK 中在 java.util 包中提供 Observable 类和 Observer 接口提供对观察者模式的语言级支持。动态代理的优点是可以动态地为软件...