动态代理原理:spring AOP采用动态代理来实现
(1)定义一个接口Boy
package aop001; public interface Boy { public void beat(String time); public void play(String time); }
(2)定义两个类实现Boy接口:
Boy_1
package aop001; public class Boy_1 implements Boy { @Override public void beat(String time) { System.out.println("我是boy1"); System.out.println(time+"敲代码"); } @Override public void play(String time) { System.out.println("我是boy1"); System.out.println(time+"玩游戏"); } }
Boy_2
package aop001; public class Boy_2 implements Boy{ @Override public void beat(String time) { System.out.println("我是boy2"); System.out.println(time+"敲代码"); } @Override public void play(String time) { System.out.println("我是boy2"); System.out.println(time+"玩游戏"); } }
(3)定义一个动态代理类并实现InvocationHandler接口
package aop001; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; public class BoyInvocationHandler implements InvocationHandler { //定义一个Object对象,保存目标 private Object targer;// 目标是不固定 //添加构造方法,可以通过构造方法给target赋值 public BoyInvocationHandler(Object targer) { this.targer = targer; } //非核心业务的代码由动态代理来管理 //定义一个前置任务的方法 private void before(){ // 前置任务 System.out.println("[代理执行前置]起床"); System.out.println("[代理执行前置]刷牙洗脸"); System.out.println("[代理执行前置]吃饭"); System.out.println("*****************"); } //定义一个后置任务的方法 private void after(){ // 后置任务 System.out.println("*****************"); System.out.println("[代理执行后置]洗澡"); System.out.println("[代理执行后置]睡觉"); System.out.println(""); } //调用invoke方法 @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { //调用前置任务的方法 before(); //获取类里面的方法的返回值 Object returnValue=method.invoke(targer, args); //调用后置任务的方法 after(); return returnValue; } }
(4)新建一个Test测试类
package aop001; import java.lang.reflect.Proxy; public class Test { public static void main(String[] args) { //第一步:创建目标实现类的实例 Boy b1=new Boy_1(); Boy b2=new Boy_2(); //第二步:创建一个动态代理类(CEO 首席执行官) BoyInvocationHandler handler1 = new BoyInvocationHandler(b1); BoyInvocationHandler handler2 = new BoyInvocationHandler(b2); //第三步:创建动态代理(跟静态代理一样,申明的变量仍然是目标的接口) Boy girlProxy1 = (Boy) Proxy.newProxyInstance( b1.getClass().getClassLoader(), b1.getClass().getInterfaces(), handler1); //调用方法 girlProxy1.beat("周六"); girlProxy1.play("周日"); Boy girlProxy2 = (Boy) Proxy.newProxyInstance( b2.getClass().getClassLoader(), b2.getClass().getInterfaces(), handler2); girlProxy2.beat("周六"); girlProxy2.play("周日"); } }
(5)运行结果:
[代理执行前置]起床
[代理执行前置]刷牙洗脸
[代理执行前置]吃饭
*****************
我是boy1
周六敲代码
*****************
[代理执行后置]洗澡
[代理执行后置]睡觉
[代理执行前置]起床
[代理执行前置]刷牙洗脸
[代理执行前置]吃饭
*****************
我是boy1
周日玩游戏
*****************
[代理执行后置]洗澡
[代理执行后置]睡觉
[代理执行前置]起床
[代理执行前置]刷牙洗脸
[代理执行前置]吃饭
*****************
我是boy2
周六敲代码
*****************
[代理执行后置]洗澡
[代理执行后置]睡觉
[代理执行前置]起床
[代理执行前置]刷牙洗脸
[代理执行前置]吃饭
*****************
我是boy2
周日玩游戏
*****************
[代理执行后置]洗澡
[代理执行后置]睡觉
(6)当我们需要更改非核心代码时,我们只要更改一处就可以了。
谢谢!