JDK和Cglib动态代理


1.代理模式(静态代理)
 代理模式是常用设计模式的一种,我们在软件设计时常用的代理一般是指静态代理,也就是在代码中显式指定的代理。
 静态代理由 业务实现类、业务代理类 两部分组成。业务实现类 负责实现主要的业务方法,业务代理类负责对调用的业务方法作拦截、过滤、预处理,主要是在方法中首先进行预处理动作,然后调用业务实现类的方法,还可以规定调用后的操作。我们在需要调用业务时,不是直接通过业务实现类来调用的,而是通过业务代理类的同名方法来调用被代理类处理过的业务方法。
UserDao.java

package com.wuhaitao.spring.demo1;

public interface UserDao {
    public void save();
}

UserDaoImpl.java

package com.wuhaitao.spring.demo1;

public class UserDaoImpl implements UserDao {
    @Override
    public void save() {
        System.out.println("用户被保存了");
    }
}

UserProxy.java

package com.wuhaitao.spring.demo1;

public class UserProxy implements UserDao {
    //组合一个业务实现类对象来进行真正的业务方法的调用
    private UserDaoImpl userDaoImpl;    
    
    public UserProxy(UserDaoImpl userDaoImpl) {
        this.userDaoImpl = userDaoImpl;
    }
    
    @Override
    public void save() {
        System.out.println("保存用户的预处理");
        userDaoImpl.save();
        System.out.println("保存用户后的操作");
    }
}

SpringTest.java

package com.wuhaitao.spring.demo1;

import org.junit.Test;

public class SpringTest {
    @Test
    public void demo1() {
        UserDaoImpl dao = new UserDaoImpl();
        UserProxy userProxy = new UserProxy(dao);
        userProxy.save();
    }
}

  静态代理的缺点很明显:一个代理类只能对一个业务接口的实现类进行包装,如果有多个业务接口的话就要定义很多实现类和代理类才行。而且,如果代理类对业务方法的预处理、调用后操作都是一样的(比如:调用前输出提示、调用后自动关闭连接),则多个代理类就会有很多重复代码。这时我们可以定义这样一个代理类,它能代理所有实现类的方法调用:根据传进来的业务实现类和方法名进行具体调用。——那就是动态代理。
2.JDK动态代理 (必须是实现接口的类,才能使用.并且,如果业务实现类中新增了接口中没有的方法,这些方法是无法被代理的(因为无法被调用)。)
UserDao.java

package com.wuhaitao.spring.demo2;

public interface UserDao {
    public void save();
    public void update();
    public void delete();
    public void select();
}

UserDaoImpl.java

package com.wuhaitao.spring.demo2;

public class UserDaoImpl implements UserDao {

    @Override
    public void save() {
        System.out.println("用户被保存了");
    }

    @Override
    public void update() {
        System.out.println("用户信息更改了");
    }

    @Override
    public void delete() {
        System.out.println("用户被删除了");
    }

    @Override
    public void select() {
        System.out.println("查找用户的信息");
    }
}

JdkProxy.java

package com.wuhaitao.spring.demo2;

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



public class JdkProxy implements InvocationHandler{
    //这其实业务实现类对象,用来调用具体的业务方法 
    private UserDao userDao;
    
    public JdkProxy(UserDao userDao) {
        this.userDao = userDao;
    }

    public UserDao createProxy() {
        //通过反射机制,创建一个代理类对象实例并返回。用户进行方法调用时使用
        //创建代理对象时,需要传递该业务类的类加载器(用来获取业务实现类的元数据,在包装方法是调用真正的业务方法)、接口、handler实现类
        UserDao userDaoProxy = (UserDao) Proxy.newProxyInstance(userDao.getClass().getClassLoader(), userDao.getClass().getInterfaces(), this);
        return userDaoProxy;
    }
    
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        if("save".equals(method.getName())) {
            System.out.println("增强了");
            return method.invoke(userDao, args);
        }
        return method.invoke(userDao, args);
    }
}

SpringTest.java

package com.wuhaitao.spring.demo2;

import org.junit.Test;

public class SpringTest {
    @Test
    public void test() {
        UserDao userDao = new UserDaoImpl();
        UserDao proxy = new JdkProxy(userDao).createProxy();
        proxy.save();
        proxy.delete();
        proxy.select();
        proxy.update();
    }
}

3.Cglib动态代理
  cglib是针对类来实现代理的,原理是对指定的业务类生成一个子类,并覆盖其中业务方法实现代理。因为采用的是继承,所以不能对final修饰的类进行代理。
UserDaoImpl.java

package com.wuhaitao.spring.demo3;

public class UserDaoImpl {

    public void save() {
        System.out.println("用户被保存了");
    }

    public void update() {
        System.out.println("用户信息更改了");
    }

    public void delete() {
        System.out.println("用户被删除了");
    }

    public void select() {
        System.out.println("查找用户的信息");
    }

}

CglibProxy.java

package com.wuhaitao.spring.demo3;

import java.lang.reflect.Method;

import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;

public class CglibProxy implements MethodInterceptor{
    private UserDaoImpl userDaoImpl;

    public CglibProxy(UserDaoImpl userDaoImpl) {
        this.userDaoImpl = userDaoImpl;
    }
    
    //使用cglib产生代理的方法
    public UserDaoImpl creqateProxy() {
        //创建cglib的核心类对象
        Enhancer enhancer = new Enhancer();
        //设置父类
        enhancer.setSuperclass(userDaoImpl.getClass());
        //设置回调
        enhancer.setCallback(this);
        //创建代理对象
        UserDaoImpl proxy = (UserDaoImpl) enhancer.create();
        return proxy;
    }

    @Override
    public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
        if("save".equals(method.getName())) {
            System.out.println("增强了。。。。");
            return methodProxy.invokeSuper(proxy, args);
        }
        return methodProxy.invokeSuper(proxy, args);
    }
}

SpringTest.java

package com.wuhaitao.spring.demo3;

import org.junit.Test;

public class SpringTest {
    @Test
    public void test() {
        UserDaoImpl userDaoImpl = new UserDaoImpl();
        UserDaoImpl userDaoImplProxy = new CglibProxy(userDaoImpl).creqateProxy();
        userDaoImplProxy.save();
        userDaoImplProxy.delete();
        userDaoImplProxy.update();
        userDaoImplProxy.select();
    }
}

你可能感兴趣的:(JDK和Cglib动态代理)