首页 > 编程语言 >java动态代理和静态代理的实现

java动态代理和静态代理的实现

时间:2023-01-10 11:33:31浏览次数:41  
标签:java 静态 代理 目标 doFirst doSecond UserService public


代理模式:为其他对象提供一种代理以控制目标对象的访问,在某些情况下, 一个对象不适合或者不能直接引用另外一个对象,代理对象可以在这个客户类和目标对象中起到一个桥梁作用。

简单来说,代理对象的使用,是在不修改原有目标对象的基础上,增强原有目标对象的功能逻辑。

代理的实现有两种,静态代理和动态代理,而动态代理,又分为jdk动态代理和cglib动态代理。

本文目录:

  • 1.静态代理的实现
  • 2.jdk动态代理的实现
  • 3.cglib动态代理的实现

1.静态代理

需要目标类实现接口,代理类和目标类实现相同的接口,静态代理,是有代理类的,而动态代理是没有的。

1.1定义接口类UserService

package com.java4all.test_proxy_static;

/**
* author:lightClouds917
* date:2018/10/7
* description:接口
*/
public interface UserService {

String doFirst();

void doSecond();
}

1.2定义接口类的实现类

也就是我们的目标类,我们需要增强的类

package com.java4all.test_proxy_static;

/**
* author:lightClouds917
* date:2018/10/7
* description:接口实现类 目标类,等待增强
*/
public class UserServiceImpl implements UserService{
@Override
public String doFirst() {
System.out.println("执行了doFirst()方法");
return "iloveyou";
}

@Override
public void doSecond() {
System.out.println("执行了doSecond()方法");
}
}

1.3定义目标类的代理类

要和目标类实现相同的接口,在此代理类的方法中进行增强

package com.java4all.test_proxy_static;

import org.springframework.stereotype.Service;

/**
* author:lightClouds917
* date:2018/10/7
* description:静态代理 有代理类
* 在代理类中增强目标类的方法
*/
@Service
public class UserServiceImplProxy implements UserService{

@Override
public String doFirst() {
//调用目标类的原始方法
UserServiceImpl userService = new UserServiceImpl();
String str = userService.doFirst();
//增强逻辑 这里以字母转换为例
str = str.toUpperCase();
return str;
}

@Override
public void doSecond() {
UserService userService = new UserServiceImpl();
userService.doSecond();
}
}

1.4测试

测试一下,原本目标类中有个方法是返回iloveyou,在代理类中,我们对此方法进行了增强,将字母转为了大写进行返回。

package com.java4all.test_proxy_static;

/**
* author:lightClouds917
* date:2018/10/7
* description:测试静态代理
*/
public class TestProxy {

public static void main(String[]args){
test1();
System.out.println("--------------");
test2();
}

/**
* 调用原有的目标对象来实现功能
*/
public static void test1(){
UserService userService = new UserServiceImpl();
System.out.println(userService.doFirst());
userService.doSecond();
}

/**
* 调用代理对象来实现功能
*/
public static void test2(){
UserService userServiceImplProxy = new UserServiceImplProxy();
System.out.println(userServiceImplProxy.doFirst());
userServiceImplProxy.doSecond();
}
}

测试结果如下:

执行了doFirst()方法
iloveyou
执行了doSecond()方法
--------------
执行了doFirst()方法
ILOVEYOU
执行了doSecond()方法

2.jdk动态代理

jdk动态代理的原理是,和目标类实现共同的接口,由Proxy.newProxyInstance生成一个代理对象,在代理对象调用方法时,在invoke方法中增强。

jdk动态代理,不需要代理类,他的实现必须是要求目标类实现了某个接口,然后代理对象和目标类实现了相同的接口。

2.1定义接口

package com.java4all.test_proxy_jdk;

/**
* author:lightClouds917
* date:2018/10/7
* description:接口
*/
public interface UserService {

String doFirst();

void doSecond();
}

2.2定义实现类

也就是需要增强的目标类

package com.java4all.test_proxy_jdk;

/**
* author:lightClouds917
* date:2018/10/7
* description:接口实现类 目标类,等待增强
*/
public class UserServiceImpl implements UserService {
@Override
public String doFirst() {
System.out.println("执行了doFirst()方法");
return "iloveyou";
}

@Override
public void doSecond() {
System.out.println("执行了doSecond()方法");
}
}

2.3测试jdk动态代理

package com.java4all.test_proxy_jdk;

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

/**
* author:lightClouds917
* date:2018/10/7
* description:jdk动态代理
* 没有代理类
* 由Proxy.newProxyInstance生成一个代理对象,在调用方法时,在invoke方法中增强
* 要求:目标类存在接口,目标类和代理对象要实现相同的接口
*/
public class TestProxy {

public static void main(String[]args){
test1();
}

public static void test1(){
//目标类对象
UserService target = new UserServiceImpl();

/**jdk动态代理,没有代理类,由Proxy.newProxyInstance生成一个代理对象*/
UserService userService = (UserService)Proxy.newProxyInstance(
target.getClass().getClassLoader(),//目标类的类加载器
target.getClass().getInterfaces(), //目标类实现的所有接口
new InvocationHandler() { //匿名内部类

//proxy:代理对象
//method:目标方法
//args:目标方法参数列表
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object invoke = method.invoke(target, args);
if(invoke != null){
return invoke.toString().toUpperCase();
}
return null;
}
});
System.out.println(userService.doFirst());
userService.doSecond();
}

}

结果:

执行了doFirst()方法
ILOVEYOU
执行了doSecond()方法

3.cglib动态代理

cglib动态代理的原理是,生成目标类的子类,在子类中进行增强,这个子类对象就是代理对象。

使用cglib代理时,要求目标类必须可以被继承,即没有用final修饰。

CGLIB(code generation Library)是一个开源项目,是一个强大的,高性能的,高质量的代码生成类库。他可以在运行期间拓展和增强java类,Spring用它来实现AOP编程。

3.1目标类UserService

不需要实现接口

package com.java4all.test_proxy_cglib;

/**
* author:lightClouds917
* date:2018/10/7
* description:目标类,没有实现接口,等待增强
*/
public class UserService {

public String doFirst() {
System.out.println("执行了doFirst()方法");
return "iloveyou";
}

public void doSecond() {
System.out.println("执行了doSecond()方法");
}
}

3.2代理工厂

用来生成目标类的代理对象,此类需要实现MethodInterceptor

package com.java4all.test_proxy_cglib;

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

import java.lang.reflect.Method;

/**
* author:lightClouds917
* date:2018/10/7
* description:返回目标类的代理对象
* 需要实现MethodInterceptor
*/
public class MyCglib implements MethodInterceptor{

private UserService target;

public MyCglib(UserService target) {
this.target = target;
}

/**
* 返回目标类的代理对象
* @return
*/
public UserService MyCglibCreator(){
Enhancer enhancer = new Enhancer();
//指定父类,即目标类 cglib原理:子类增强父类
enhancer.setSuperclass(UserService.class);
//设置回调接口 当前类继承了MethodInterceptor,
//此接口public interface MethodInterceptor extends Callback
enhancer.setCallback(this);
//create创建cglib动态代理对象
return (UserService)enhancer.create();
}


//回调接口的方法 代理对象执行目标方法时,会触发该方法
@Override
public Object intercept(Object o,
Method method,
Object[] objects,
MethodProxy methodProxy) throws Throwable {
Object invoke = method.invoke(target, objects);
if(invoke != null){
return invoke.toString().toUpperCase();
}
return invoke;
}
}
3.3测试cglib动态代理
package com.java4all.test_proxy_cglib;


/**
* author:lightClouds917
* date:2018/10/7
* description:cglib动态代理
*/
public class TestProxy {

public static void main(String[]args){
test1();
}

public static void test1(){
UserService target = new UserService();

//调用工厂类获取代理对象
MyCglib myCglib = new MyCglib(target);
UserService userService = myCglib.MyCglibCreator();

System.out.println(userService.doFirst());
userService.doSecond();
}

}


标签:java,静态,代理,目标,doFirst,doSecond,UserService,public
From: https://blog.51cto.com/u_15936016/5999930

相关文章

  • Java下载多个网络文件并打成压缩包
    需求:浏览器访问后台的http地址后,后台将多个网络文件打成压缩包返回给浏览器,用户可以通过浏览器直接下载压缩包。实现:根据文件链接把文件下载下来并且转成字节码 ,代码:pac......
  • java socket通信
    1.socket通信模型2.代码示例2.1服务端packagecom.java4all.controller;importjava.io.*;importjava.net.ServerSocket;importjava.net.Socket;/***Author:yunqing*......
  • static静态代码块加载和执行
    静态代码块,非静态代码块,无参构造,有参构造,这些代码片段分别在什么时候加载执行?1.父类Fatherpackagecom.java4all.test10;publicclassFather{static{System.......
  • java反射field相关知识
    Classc=ArrayList.class;c.isPrimitive();//判断c是否为基本数据类型c.isAssignableFrom(List.class);//判断c是否是List类的子类或父类c.getGenericType();//......
  • 如何理解Java的一处编译处处运行
    要理解Java的一处编译处处运行这句话,首先需要知道平台的概念;什么是平台 CPU处理器与操作系统的整体叫平台。CPU:每种CPU又有特定的指令集;操作系统:不同的操作系统支......
  • 14个非常棒的 JavaScript 游戏开发框架推荐
     ​​LimeJS​​​​​​这是一个基于HTML5游戏框架,用于快速构建运行于现代触摸屏和桌面浏览器的游戏(需要***访问)。 ​​Impact​​​​​​ 这是一个专业的JavaScript......
  • Java循环运行时暂停一段时间
    GitHub项目地址Gitee项目地址Java在运行for循环时,希望可以每个循环暂停一段时间。使用sleep方法即可:for(inti=0;i<10;i++){try{System.ou......
  • 【项目源码】基于JavaEE的健康管理系统
    随着网络技术的不断发展,网站的开发与运用变得更加广泛。这次采用java语言SSH框架(Spring,Struts,Hibernate)设计并实现了面向特定群体的健康管理平台。该网站主要有教师饮食管......
  • [项目源码] JavaWeb校园宿舍管理系统
     jsp校园宿舍管理系统源码,采用Servlet+JSP+MySQL。包含数据库文件,界面采用bootstrap,简洁大方。      项目导入eclipse后的目录结构如下: 关注下面公众号,下载源码原......
  • Java循环运行时暂停一段时间
    GitHub项目地址Gitee项目地址Java在运行for循环时,希望可以每个循环暂停一段时间。使用sleep方法即可:for(inti=0;i<10;i++){try{System.o......