发表于: 2020-03-10 23:24:00

1 1262


用java 的动态代理实现AOP来了解AOP的原理.

1. 创建一个接口测试类

public interface UserDao {
   int insertUser();
   void updateUser();
   void findUser();
   void deleteUser();
}

public class UserDaoImpl implements UserDao {
   @Override
   public int insertUser() {
       System.out.println("insertUser() 添加执行了....");
       return 111;
   }
   @Override
   public void updateUser() {
       System.out.println("updateUser() 更新执行了....");
   }
   @Override
   public void findUser() {
       System.out.println("查找....");
   }
   @Override
   public void deleteUser() {
       System.out.println("deleteUser() 删除执行了....");
   }
}

实现Java动态代理接口 InvocationHandler 重写invoke()方法 

package com.jnshu.InvocationHandleraop.dao;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

/**
* 动态代理
**/

// 要使用java的动态代理必须实现它的InvocationHandler接口方法invoke()
public class LogIntercept implements InvocationHandler{
   // 准备接收代理对象的属性
   // 动态代理的好处,被封装的对象是Object类型,接受任意类型的对象
   private Object terget;

   // 设置要代理的方法对象
   public void setTerget(Object terget) {
       this.terget = terget;
   }

   // 插入到代理方法开始前
   public void beforeMethod(){
       System.out.println("接口方法 开始...");
   }
   // 插入到代理方法接收后
   public void afterMethod(){
       System.out.println("接口方法 结束...");
   }

   /**
   *  重写的 InvocationHandler 动态代理接口方法
   *  method是调用的方法,即需要执行的方法;args是方法的参数;
   *  Proxy懒得查
   *
   @Override
   public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
       // 在方法执行前运行
       beforeMethod();
       // 执行代理的方法 无论调用代理对象的哪个方法,invoke方法都要被调用
       method.invoke(terget, args);
       // 在方法执行后运行
       afterMethod();
       return null;
   }
}

测试 

package com.jnshu.InvocationHandleraop.dao;

import com.jnshu.springaop.dao.UserDao;
import com.jnshu.springaop.dao.impl.UserDaoImpl;
import org.junit.Test;

import java.lang.reflect.Field;
import java.lang.reflect.Proxy;

import static org.junit.Assert.*;

public class LogInterceptTest {

   //test:生成代理实例,并调用了updateUser()方法
   @Test
   public void invoke() {
       // 抽象角色(动态代理只能代理接口)
       UserDao userDao = new UserDaoImpl();
       // 创建代理对象
       LogIntercept logIntercept = new LogIntercept();
       // 指定被代理的接口对象
       logIntercept.setTerget(userDao);

       // 一次性生成代理 使用Proxy的newProxyInstance去代理接口对象的,内部再去调用 LogIntercept中重写的invoke, 不是直接调用重写的 invoke方法
       UserDao userDaoProxy = (UserDao) Proxy.newProxyInstance(
               // getClass():取得当前对象所属的Class对象
               // getClassLoader():取得该Class对象的类装载器,保证是和 类 类型同一个加载器加载的
               userDao.getClass().getClassLoader(),
               // 为一个class数组分配空间,并且第一个元素是UserDao类, 这个我也看不懂=.=
               new Class[]{UserDao.class},
               // 传入代理对象
               logIntercept
       );

       // 这里可以通过运行结果证明userDaoProxy是Proxy的一个实例,这个实例实现了userDao接口
       System.out.println((userDaoProxy instanceof Proxy) + " 这里证明userDaoProxy是Proxy的一个实例,这个实例实现了userDaoProxy接口");

       // 这里可以看出userDaoProxy的Class类是$Proxy4,这个$Proxy4类继承了Proxy,实现了userDao接口
       System.out.println("userDaoProxy的Class类是:" + userDaoProxy.getClass().toString());

       System.out.print("userDaoProxy中的属性有:\n");
       // getDeclaredFields()方法和Java的反射机制有关.
       // 返回 Field 对象的一个数组,该数组包含此 Class 对象所表示的类或接口所声明的所有字段(包括私有成员)
       Field[] field = userDaoProxy.getClass().getDeclaredFields();
       // 遍历 field 集合
       for (Field field1 : field) {
           System.out.println(field1.getName() + ", ");
       }

       System.out.println("userDaoProxy的父类是:" + userDaoProxy.getClass().getSuperclass());

       System.out.print("userDaoProxy实现的接口是:");
       // getInterfaces()方法和Java的反射机制有关. 它能够获得这个对象所实现的接口。
       Class<?>[] interfaces = userDaoProxy.getClass().getInterfaces();
       for (Class<?> i : interfaces) {
           System.out.print(i.getName() + "\n");
       }

       // 执行接口方法测试
       System.out.println("\n===测试接口是否被代理了===");
       userDaoProxy.updateUser();
       System.out.println("");
       userDaoProxy.deleteUser();
   }
}

输出结果,已被成功代理 : 

true 这里证明userDaoProxy是Proxy的一个实例,这个实例实现了userDaoProxy接口
userDaoProxy的Class类是:class com.sun.proxy.$Proxy4
userDaoProxy中的属性有:
  m1,
   m5,
   m2,
   m6,
   m0,
   m3,
   m4,
userDaoProxy的父类是:class java.lang.reflect.Proxy
userDaoProxy实现的接口是:com.jnshu.springaop.dao.UserDao


---测试接口是否被代理了---

   接口方法 开始...
updateUser() 更新执行了....
   接口方法 结束...

接口方法 开始...
deleteUser() 删除执行了....
   接口方法 结束...

结果:没有显示的调用invoke()方法,方法却执行了。

今日问题 无




返回列表 返回列表
评论

    分享到