1. 动态代理
动态代理:在程序运行时,运用反射机制动态创建而成。
1、 动态代理和静态代理的角色是一样的。
2、 动态代理的代理类是动态生成的。
3、 分为两类一类基于接口动态代理和基于类的动态代理。
a) 基于接口动态代理---jdk动态代理
i. Java动态代理使用Proxy类和InvocationHandler接口。
ii. 使用Proxy类做代理的时候,必须有InvocationHandler对象。
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, throws IllegalArgumentException
loader - 定义代理类的类加载器 interfaces - 代理类要实现的接口列表 h - 指派方法调用的调用处理程序 Object: 因为不能确定要代理的对象是什么类型,所以要返回类的祖先! 是谁创建的动态代理? InvocationHandler: invoke Method method, Object[] args) throws Throwable proxy - 在其上调用方法的代理实例
method - 对应于在代理实例上调用的接口方法的 Method 实例。Method 对象的声明类将是在其中声明方法的接口,该接口可以是代理类赖以继承方法的代理接口的超接口。
args - 包含传入代理实例上方法调用的参数值的对象数组,如果接口方法不使用参数,则为 null。基本类型的参数被包装在适当基本包装器类(如 java.lang.Integer 或 java.lang.Boolean)的实例中。 利用静态代理中的例子来解释: Proxy: 中介UserProxy Method:rent()方法 Args:参数:null |
b) 基于类的动态代理---cglib
i. 对指定的目标类生成一个子类,并覆盖其中方法实现增强,但因为采用的是继承,所以不能对final修饰的类进行代理。
案例:使用动态代理,在每个方法执行前,添加一句话【方法被执行了】。
1、在UserDao接口中层创建四个方法:CRUD
2、在UserDaoImpl类中实现四个方法:CRUD
3、创建一个代理类实现InvocationHandler接口中的invoke方法。
动态代理实现步骤:
1、 创建一个类来实现InvocationHandler接口。实现invoke方法()
a) Invoke方法中就是具体的你要实现的功能!
i. 输出我们的“方法被执行了!”
2、 在该接口中创建动态代理。Proxy. newProxyInstance(参数1,参数2,参数3);
3、 测试!
代码:
public interface UserDao { void add(); void delete(); void update(); void search(); String show(); }
public class UserDaoImpl implements UserDao {
@Override public void add() { System.out.println("添加用户"); } @Override public void delete() { System.out.println("删除用户"); }
@Override public void update() { System.out.println("更新用户"); }
@Override public void search() { System.out.println("查询用户"); } @Override public String show() { return "show"; } }
public class UserDaoProxy implements InvocationHandler { // 声明要代理的对象 private Object object;
public Object getObject() { return object; }
// 给代理对象赋值 public void setObject(Object object) { this.object = object; }
// 如何创建一个代理对象?使用Proxy类来创建 public Object getProxy() { // 第一个参数是类加载器,第二个参数是代理对象的接口,第三个是InvocationHandler 对象 return Proxy.newProxyInstance(this.getClass().getClassLoader(), object.getClass().getInterfaces(), this); }
/** * proxy 代理的对象 method 代理对象的方法 args 参数数组 */
@Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { txStart(); // obj:被代理的对象!args:参数数组,说白了。 method.invoke(object, args) 就是执行真是代理对象的方法。 Object obj = method.invoke(object, args); System.out.println(obj+"=========="); txClose(); return obj; }
public void txStart() { System.out.println("开启事务!"); }
public void txClose() { System.out.println("关闭事务!"); }
} 测试: public class Test { public static void main(String[] args) { // 创建代理对象 UserDaoProxy u = new UserDaoProxy(); // 创建代理对象 ,说明你要代理的那个类 UserDao ud = new UserDaoImpl(); u.setObject(ud); // 得到代理对象! UserDao userDao = (UserDao) u.getProxy(); // 代理类的方法被执行的时候,则会调用InvocationHandler中的invoke方法。 userDao.add(); userDao.delete(); userDao.search(); userDao.show();
} } 能否将租房改成动态代理。 注意:InvocationHandler 的invoke、方法 和 method.invoke方法不一样! |