java的代理

1. 什么是代理

  代理对象包含目标对象,在目标对象的基础上增加一些功能

  举个例子:进行数据库操作,目标对象只需写实现即可,事务交给代理对象去做

2. 静态代理:

  在不改变目标对象的情况下,对目标对象进行扩展

  

public interface UserDao {
    void delete (Long id);
}
public class UserDaoImpl implements UserDao{
    public void delete (Long id) {
        System.out.println("删除操作");
    }
}
public class UserDaoProxy implements UserDao{

    private UserDao userDao;
    
    public UserDaoProxy(UserDao userDao) {
        this.userDao = userDao;
    }

    @Override
    public void delete(Long id) {
        this.startTransaction();
        userDao.delete(id);
        this.commitTransaction();
        
    }

    private void commitTransaction() {
        System.out.println("提交事务");
    }

    private void startTransaction() {
        System.out.println("开启事务");
    }
    

}
    public static void main(String[] args) {
        UserDaoProxy proxy = new UserDaoProxy(new UserDaoImpl());
        proxy.delete(1L);
    }

=========输出=============

开启事务
删除操作
提交事务

 缺点:代码可扩展性差,此时新增一个OrderDao,那么又要为OrderDao写一个代理类,太麻烦了。解决方法是使用动态代理

 3. jdk动态代理

  Jvm虚拟机在运行期间动态的创建代理类对象,因为是运行期间动态创建的,所以这个代理类对象是没有对应的java文件的

public interface UserDao {
    void delete (Long id);
}
public class UserDaoImpl implements UserDao{
    public void delete (Long id) {
        System.out.println("删除操作");
    }
}
public class TransactionManagerProxy implements InvocationHandler{
    
    private Object target;
    
    public <T> void setTarget(T target) {
        this.target = target;
    }
    
    public <T> T getProxyObject(){
        
        T t = (T) Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
        
        return t;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        this.startTransaction();//代理对象-开启事务
        //target 为目标对象
        Object result = method.invoke(target, args);//目标对象原有操作
        this.commitTransaction();//代理对象-提交事务
        return result;
    }
    
    private void commitTransaction() {
        System.out.println("提交事务");
    }

    private void startTransaction() {
        System.out.println("开启事务");
    }

}
    public static void main(String[] args) {
        TransactionManagerProxy proxy = new TransactionManagerProxy();
        UserDao userDao = new UserDaoImpl();
        proxy.setTarget(userDao);
        UserDao userDaoProxy = proxy.getProxyObject();
        userDaoProxy.delete(1L);
    }

=========输出=============

开启事务
删除操作
提交事务

4. cglib动态代理

  和jdk动态代理的区别是jdk动态代理的目标对象必须要有接口,而cglib则不需要,因为cglib是通过继承的方式来调用目标对象的方法

public class UserDaoImpl{
    public void delete (Long id) {
        System.out.println("删除操作");
    }
}
public class TransactionManagerCglibProxy implements InvocationHandler{

    private Object target;
    
    public <T> void setTarget(T target) {
        this.target = target;
    }
    
    public <T> T getProxyObject() {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(target.getClass());//目标类的类型,用继承的方式进行代理
        enhancer.setCallback(this);//增强处理
        return (T) enhancer.create();
    }
    
    
    private void commitTransaction() {
        System.out.println("提交事务");
    }

    private void startTransaction() {
        System.out.println("开启事务");
    }
    
    @Override
    public Object invoke(Object obj, Method method, Object[] args) throws Throwable {
        this.startTransaction();
        Object result = method.invoke(target, args);
        this.commitTransaction();
        return result;
    }

}
    public static void main(String[] args) {
        UserDaoImpl userDaoImpl = new UserDaoImpl();
        TransactionManagerCglibProxy proxy = new TransactionManagerCglibProxy();
        proxy.setTarget(userDaoImpl);
        UserDaoImpl userDaoProxy = proxy.getProxyObject();
        userDaoProxy.delete(1L);
    }

=========输出=============

开启事务
删除操作
提交事务

原文地址:https://www.cnblogs.com/zhangzonghua/p/12849196.html