一、动态代理:
1.在原有的静态代理的基础上进一步的完善,由于静态代理中,重复写了相同的代码使得代码的整体结构显得冗余,而且还不同的核心类还需要有不用的代理类,是写死了的具体的类。所以需要使用动态代理来代替静态代理。
2.具体实例:
⑴、业务介绍:
假定高三学生为核心类,学生的家人是代理类。高三学生需要做的核心业务有:在家学习(studyAtHome)、在学校学习(studyAtHome);家人需要做的非核心业务为:准备饭菜(买、洗、炒、煮饭)。准备补品(购买、熬制、加佐料)。
⑵、创建一个高三学生接口:G3Student
package aop_002; //首先定义一个接口,用来高三学生来是实现, //在这个接口中声明一个在家学习和一个在学校学习的方法 public interface G3Student { public void studyAtHome(String core); public void studyAtSchool(String core); }
⑶、创建一个高三学生(G3Student_boy),实现高三学生接口(G3Student),这个高三学生的类就是核心类。
package aop_002; /* * 本例演示的是动态代理 */ //定义一个高三学生的类(目标对象、核心对象、target对象),实现了高三学生的接口。 public class G3Student_boy implements G3Student { //高三学生 的第一个业务流程:在家学习 public void studyAtHome(String core) { //核心的事情是在家学习。 System.out.println(core+"在HOME学习"); } //高三学生 的第二个业务流程:在学校学习 public void studyAtSchool(String core) { //核心的事情是在家学习。 System.out.println(core+"在SCHOOOL学习");
} }
⑷、创建一个高三学生的代理类(G3Student_handler),并且实现了InvocationHandler接口
package aop_002;
import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; public class G3Student_handler implements InvocationHandler { private Object g3Stu; public G3Student_handler(Object g3Stu) { this.g3Stu = g3Stu; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { //调用代理的在核心对象处理核心业务之前的方法 before(); //核心对象的核心方法 Object returnValue = method.invoke(g3Stu, args); //调用代理的在核心对象处理核心业务之后的方法 after(); return returnValue; } private void before(){ //这个是代理(G3Student_handler)准备饭菜的需要做的流程: System.out.println("代理:准备买菜"); System.out.println("代理:准备洗菜"); System.out.println("代理:准备炒菜"); System.out.println("代理:准备煮饭"); System.out.println("-----------------"); } private void after(){ //这个是代理(G3Student_handler)准备补品的需要做的流程: System.out.println("-----------------"); System.out.println("代理 :购买补品"); System.out.println("代理 :熬制部品"); System.out.println("代理 :加入佐料"); System.out.println(); } }
①、其中,和静态代理不同的是,动态代理的代理类中定义了一个以Object类型的属性,而静态代理定义的是具体的G3Student的接口类型的属性。所以,动态代理这样定义保证了,这个代理可以带不同的个核心类如:G3Student_boy、G3Student_girl。
②、这句代码意思:自动调用传入的核心类对象(G3Student_boy)的方法,并且传入参数args,返回一个Object类型的值。具体是调用什么方法,传入什么参数,都不需要我们具体关注,只需写上这条代码,并且把返回值返回即可。
⑸、创建一个测试类Test:
package aop_002; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Proxy; public class Test { public static void main(String[] args) { G3Student boy = new G3Student_boy(); InvocationHandler handler1 = new G3Student_handler(boy);
G3Student g3boy = (G3Student)Proxy.newProxyInstance(boy.getClass().getClassLoader(), boy.getClass().getInterfaces(),handler1); g3boy.studyAtSchool("小明"); g3boy.studyAtHome("小明"); } }
①、首先,需要创建一个高三学生对象,其次需要创建一个代理类对象,最后使用Proxy创建一个高三学生对象,再调用方法即可。
②、可能有的人会问,为什么不直接使用第一次创建的高三学生对象直接调用方法呢?如果使用第一次创建的高三学生对象直接调用方法,那么就没有代理做的事情显示,所以应该时候用Proxy创建的高三学生对象,Proxy等于是高三学生对象和代理对象进行一次整合,使它们两个有机结合在一起,各自做各自的事情。
测试结果:
谢谢浏览!