Spring基础:代理模式介绍
Posted Lansonli
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring基础:代理模式介绍相关的知识,希望对你有一定的参考价值。
目录
代理模式介绍
代理模式是通过代理对象访问目标对象,这样可以在目标对象基础上增强额外的功能,如添加权限,访问控制和审计等功能。
例如:房产中介代替业主卖房
一、静态代理
静态代理中代理类与被代理类都需要实现同一个接口,这就说明我们的一个静态代理类只能代理一个类,并且还要事先知道我们要代理哪个类才能写代理类,如果我们有其他类还想使用代理那就必须再写一个代理类。然而在实际开发中我们是可能是有非常多的类是需要被代理的,并且事先我们可能并不知道我们要代理哪个类。所以如果继续使用静态代理反而会增加许多的工作量,并且效率低下,代码复用率也不好。
package com.lanson.test;
/**
* @Author: Lansonli
* @Description: MircoMessage:Mark_7001
*/
public class Test1
public static void main(String[] args)
Person person =new Person("张三");
Court court=new Lawyer(person);
court.doCourt();
// 接口
interface Court
void doCourt();
// 代理类
class Lawyer implements Court
private Person person;
public Lawyer(Person person)
this.person = person;
@Override
public void doCourt()
System.out.println("律师取证:视频证明张三当时正在旅游,不在案发现场");
System.out.println("律师总结:张三不可能去杀人");
person.doCourt();
// 被代理的类
class Person implements Court
private String name;
public Person(String name)
this.name = name;
@Override
public void doCourt()
System.out.println(name+"说:我没有杀人");
二、动态代理
动态代理可以针对于一些不特定的类或者一些不特定的方法进行代理,我们可以在程序运行时动态的变化代理的规则,代理类在程序运行时才创建的代理模式成为动态代理。这种情况下,代理类并不是在Java代码中定义好的,而是在程序运行时根据我们的在Java代码中的“指示”动态生成的
Proxy动态代理 JDK动态代理 面向接口
cglib动态代理 第三方动态代理 面向父类
1、Proxy动态代理
- 必须有接口和实现类
- 增强接口中定义的方法
- 只能读取接口中方法的上注解
代码举例:张三吃饭
package com.lanson.testProxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Arrays;
/**
* @Author: Lansonli
* @Description: MircoMessage:Mark_7001
*/
public class Test1
public static void main(String[] args)
Dinner dinner=new Person("张三");
// 通过Porxy动态代理获得一个代理对象,在代理对象中,对某个方法进行增强
// ClassLoader loader,被代理的对象的类加载器
ClassLoader classLoader = dinner.getClass().getClassLoader();
// Class<?>[] interfaces,被代理对象所实现的所有接口
Class[] interaces= dinner.getClass().getInterfaces();
// InvocationHandler h,执行处理器对象,专门用于定义增强的规则
InvocationHandler handler = new InvocationHandler()
// invoke 当我们让代理对象调用任何方法时,都会触发invoke方法的执行
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
// Object proxy, 代理对象
// Method method,被代理的方法
// Object[] args,被代理方法运行时的实参
Object res=null;
if(method.getName().equals("eat"))
System.out.println("饭前洗手");
// 让原有的eat的方法去运行
res =method.invoke(dinner, args);
System.out.println("饭后刷碗");
else
// 如果是其他方法,那么正常执行就可以了
res =method.invoke(dinner, args);
return res;
;
Dinner dinnerProxy =(Dinner) Proxy.newProxyInstance(classLoader,interaces,handler);
//dinnerProxy.eat("包子");
dinnerProxy.drink();
interface Dinner
void eat(String foodName);
void drink();
class Person implements Dinner
private String name;
public Person(String name)
this.name = name;
@Override
public void eat(String foodName)
System.out.println(name+"正在吃"+foodName);
@Override
public void drink( )
System.out.println(name+"正在喝茶");
class Student implements Dinner
private String name;
public Student(String name)
this.name = name;
@Override
public void eat(String foodName)
System.out.println(name+"正在食堂吃"+foodName);
@Override
public void drink( )
System.out.println(name+"正在喝可乐");
使用代理技术获得代理对象代替张三增强打官司的方法
2、Cglib动态代理
面向父类
package com.lanson.testCglib;
import org.junit.Test;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
/**
* @Author: Lansonli
* @Description: MircoMessage:Mark_7001
*/
public class Test1
@Test
public void testCglib()
Person person =new Person();
// 获取一个Person的代理对象
// 1 获得一个Enhancer对象
Enhancer enhancer=new Enhancer();
// 2 设置父类字节码
enhancer.setSuperclass(person.getClass());
// 3 获取MethodIntercepter对象 用于定义增强规则
MethodInterceptor methodInterceptor=new MethodInterceptor()
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable
/*Object o, 生成之后的代理对象 personProxy
Method method, 父类中原本要执行的方法 Person>>> eat()
Object[] objects, 方法在调用时传入的实参数组
MethodProxy methodProxy 子类中重写父类的方法 personProxy >>> eat()
*/
Object res =null;
if(method.getName().equals("eat"))
// 如果是eat方法 则增强并运行
System.out.println("饭前洗手");
res=methodProxy.invokeSuper(o,objects);
System.out.println("饭后刷碗");
else
// 如果是其他方法 不增强运行
res=methodProxy.invokeSuper(o,objects); // 子类对象方法在执行,默认会调用父类对应被重写的方法
return res;
;
// 4 设置methodInterceptor
enhancer.setCallback(methodInterceptor);
// 5 获得代理对象
Person personProxy = (Person)enhancer.create();
// 6 使用代理对象完成功能
personProxy.eat("包子");
class Person
public Person( )
public void eat(String foodName)
System.out.println("张三正在吃"+foodName);
三、总结
1、在不修改原有代码的或者没有办法修改原有代码的情况下增强对象功能使用代理对象代替原来的对象去完成功能,进而达到拓展功能的目的
2、JDK Proxy 动态代理面向接口的动态代理一定要有接口和实现类的存在 代理对象增强的是实现类 在实现接口的方法重写的方法
- 生成的代理对象只能转换成接口的,不能转换成被代理类
- 代理对象只能增强接口中定义的方法,实现类中其他和接口无关的方法是无法增强的
- 代理对象只能读取到接口中方法上的注解,不能读取到实现类方法上的注解
3、 Cglib 动态代理面向父类和接口没有直接关系,可以增强父类中定义的方法还可以增加一个类其他的方法,可以读取父类中方法上的所有注解
- 📢博客主页:https://lansonli.blog.csdn.net
- 📢欢迎点赞 👍 收藏 ⭐留言 📝 如有错误敬请指正!
- 📢本文由 Lansonli 原创,首发于 CSDN博客🙉
- 📢停下休息的时候不要忘了别人还在奔跑,希望大家抓紧时间学习,全力奔赴更美好的生活✨
以上是关于Spring基础:代理模式介绍的主要内容,如果未能解决你的问题,请参考以下文章