前言
本篇简单介绍动态代理及动态代理的创建过程。
一、动态代理功能与创建
动态代理是可以在不更改原来代码的基础上,增强方法的,本质上其实就是给原来的类找了一个代理,所有功能都可以交给代理,需要增强的功能让代理增强,而不需要增强的方法,可以由代理在重新掉原有类的方法来执行。
由于代理需要拿到原有类的功能,所有需要原有类先实现一个接口,可以理解为原有类重写了此接口的方法。
首先先创建一个类和一个接口,并给此接口写一些方法使类实现此接口。
接口代码,如下:给两个方法,一个是eat的方法,一个是study方法
public interface Person {
void eat();
void study();
}
定义一个学生类,由于get,set方法不使用,只写了getName方法,所以省略,并重写eat、study方法:
public class Student implements Person {
private String name;
private int age;
private String gender;
public Student() {
}
public Student(String name, int age, String gender) {
this.name = name;
this.age = age;
this.gender = gender;
}
public String getName() {
return name;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
", gender='" + gender + '\'' +
'}';
}
@Override
public void eat() {
System.out.println("吃饭");
}
@Override
public void study() {
System.out.println("学习");
}
}
我们就可以对方法进行增强,Proxy.newProxyInstance()可以创建代理里面需要传入三个参数,第一个是类加载器,类的字节码对象通过getClassLoader()方法获取类加载器。第二个是接口的字节码文件,第三个则是需要增强的方法。
代码如下:
public class Test {
public static void main(String[] args) {
//创建一个对象
Student student=new Student("张三",18,"男");
//创建代理
Person person = (Person) Proxy.newProxyInstance(
student.getClass().getClassLoader(),
new Class[]{Person.class},
new InvocationHandler() {
//重写方法,用于增强方法
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//增强eat方法,是可以键盘录入,并打印输出键盘录入的姓名和调用方法的对象一起吃饭
if (method.getName().equals("eat")) {
Scanner scanner=new Scanner(System.in);
String name=scanner.next();
System.out.println(name+"和"+student.getName()+"一起吃饭");
} else if (method.getName().equals("study")) {
//使用invoke调用对象本身函数.
method.invoke(student,args);
}
//因为本身不需要返回值,直接返回null即可
return null;
}
});
person.eat();
person.study();
}
}
这个就是对eat方法进行了增强,本身只是输出吃饭,而增强后则是可以键盘录入和谁一起吃饭,而又与无需对study方法进行重写,所以直接调用对象原有的方法即可。
二、对ArrayList集合进行增强
我们也可以对原有的方法进行增强,例如ArrayList集合是没有去重功能的,我们可以对其中的add方法进行增强,给其添加去重功能。
代码如下:
public class Test2 {
public static void main(String[] args) {
//先创建一个集合
List<Integer> list = new ArrayList<>();
//创建代理
List<Integer> newList = (List<Integer>) Proxy.newProxyInstance(
list.getClass().getClassLoader(),
new Class[]{List.class},
new InvocationHandler() {
//重写add方法
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//判断是否用户调用的是否是add方法,若不是则调用原有方法
if (method.getName().equals("add")) {
//判断将要添加的数据是否在集合中,,若不在,则添加到集合中,否则直接返回false
if (!list.contains(args[0])) {
method.invoke(list, args[0]);
}else {
return false;
}
} else {
method.invoke(list, args[0]);
}
return true;
}
}
);
//测试
newList.add(12);
newList.add(13);
newList.add(12);
System.out.println(list);
}
}
总结
本篇介绍了动态代理和简单的创建过程,以及简单的增强了ArrayListt的add方法