1.代理模式概述
1.1什么是代理模式
ProxyPattern(即:代理模式)23种常用的面向对象软件的设计模式之一。
代理模式的定义:为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。
作用:增强一个类中的某个方法.对程序进行扩展. Spring框架中AOP.
1.2动态代理介绍
动态代理它可以直接给某一个目标(被代理 对象)对象(实现了某个或者某些接口)生成一个代理对象,而不需要代理类存在。
动态代理与代理模式原理是一样的,只是它没有具体的代理类,直接通过反射生成了一个代理对象。
动态代理的分类
- jdk提供一个Proxy类可以直接给实现接口类的对象直接生成代理对象
- spring中动态代理:cglib
2.jdk中的动态代理的使用
2.1API介绍
Java.lang.reflect.Proxy
类可以直接生成一个代理对象
Proxy.newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
生成一个代理对象
参数1:ClassLoader loader
代理对象的类加载器 一般使用被代理对象的类加载器
参数2:Class<?>[] interfaces
代理对象的要实现的接口 一般使用的被代理对象实现的接口
参数3:InvocationHandler h
(接口)执行处理类
InvocationHandler
中的invoke(Object proxy, Method method, Object[] args)
方法:调用代理类的任何方法,此方法都会执行
-参数3.1Object proxy
:代理对象(慎用)
-参数3.2Method method
:当前执行的方法
-参数3.3Object[] args
:当前执行的方法运行时传递过来的参数
返回值:当前方法执行的返回值
2.2代码实现
/** 规范接口
* Created by liangtong.
*/
public interface Actor {
/**
* 唱歌
* @return
*/
public String sing();
/**
* 跳舞
* @return
*/
public String dance();
}
/** 目标类:刘德华类,需要被代理的类。
* Created by liangtong.
*/
public class Liudehua implements Actor {
@Override
public String sing() {
return "华仔唱歌";
}
@Override
public String dance() {
return "华仔跳舞";
}
}
public class TestProxy {
/*
1.工具类 Proxy.newProxyInstance(); 运行时创建代理类
Object object = Proxy.newProxyInstance()
2. 参数
参数1:类加载器,负责将新创建的类添加到内存中。
参数2:确定需要实现接口们,java可以多实现,需要同一个数组。
参数3:处理类,接口InvocationHandler
//调用代理类的每一个方法,都将执行处理类的invoke方法。
参数a) proxy 代理类,一般没用
参数b) method 当前执行的方法
参数c) args 方法的实际参数
*/
@Test
public void testDemo2(){
//目标类
Actor target = new Liudehua();
//1 类加载 代理对象的类加载器 责将新创建的类添加到内存中
ClassLoader classLoader = TestProxy.class.getClassLoader();
//2 接口 代理对象的要实现的接口
Class[] interfaces = {Actor.class};
//3 处理类,接口InvocationHandler
InvocationHandler invocationHandler = new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("代理收钱之后!");
return method.invoke(target,args);
}
};
//创建目标类
Actor actor = (Actor) Proxy.newProxyInstance(classLoader,interfaces,invocationHandler);
//调用方法并打印
System.out.println(actor.sing());
System.out.println(actor.dance());
}
}
2.4代码实现(加强)
public interface Person {
void eat();
void sleep(Integer hours);
}
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Wash {
}
public class Student implements Person {
@Override
public void eat() {
System.out.println("学生在吃饭");
}
@Wash
@Override
public void sleep(Integer hours) {
System.out.println("学生在睡觉,睡了" + hours + "个小时");
}
}
public class PersonFactory {
public static Person getPerson() {
//增强
Student student = new Student();
ClassLoader classLoader = student.getClass().getClassLoader();
Class<?>[] interfaces = student.getClass().getInterfaces();
Person obj = (Person) Proxy.newProxyInstance(classLoader, interfaces, new InvocationHandler() {
/**
*
* @param proxy 代理对象
* @param method 代理方法
* @param args 调用代理方法时传递的参数
* @return
* @throws Throwable
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Class<?>[] argClass = null;
if (args != null) {
argClass = new Class[args.length];
//获取所有参数的类型
for (int i = 0; i < args.length; i++) {
argClass[i] = args[i].getClass();
}
}
//获取方法名
String methodName = method.getName();
//获取原始的方法
Method originMethod = student.getClass().getMethod(methodName, argClass);
System.out.println(originMethod);
//判断方法是否需要增强
if (originMethod.isAnnotationPresent(Wash.class)) {
System.out.println("之前洗漱");
Object obj = method.invoke(student, args);
System.out.println("之后洗漱");
return obj;
}
return method.invoke(student, args);
}
});
return obj;
}
}
public class StudentTest {
@Test
public void test() {
Person person = PersonFactory.getPerson();
person.eat();
person.sleep(8);
}
}
网友评论