Spring动态代理

来源:互联网 发布:淘宝怎么打折促销 编辑:程序博客网 时间:2024/06/15 16:30

1.  动态代理

动态代理:在程序运行时,运用反射机制动态创建而成。

1、 动态代理和静态代理的角色是一样的。

2、 动态代理的代理类是动态生成的。

3、 分为两类一类基于接口动态代理和基于类的动态代理。

a)    基于接口动态代理---jdk动态代理

                i.         Java动态代理使用Proxy类和InvocationHandler接口。

               ii.         使用Proxy类做代理的时候,必须有InvocationHandler对象。

public static Object newProxyInstance(ClassLoader loader,

                                      Class<?>[] interfaces,

                                      InvocationHandler h)

                               throws IllegalArgumentException

 

loader - 定义代理类的类加载器

interfaces - 代理类要实现的接口列表

h - 指派方法调用的调用处理程序

Object: 因为不能确定要代理的对象是什么类型,所以要返回类的祖先!

是谁创建的动态代理?

InvocationHandler:

invoke(Object proxy,Method method,Object[] args)

Object invoke(Object proxy,

              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 Objectobject;

 

    public Object getObject() {

        returnobject;

    }

 

    // 给代理对象赋值

    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(Objectproxy, Method method, Object[]args) throws Throwable {

        txStart();

        // obj:被代理的对象!args:参数数组,说白了。 method.invoke(object, args) 就是执行真是代理对象的方法。

        Object obj = method.invoke(object, args);

        System.out.println(obj+"==========");

        txClose();

        returnobj;

    }

 

    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方法不一样!

原创粉丝点击