• 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);
        }

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

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

  • 相关阅读:
    reflow和repaint
    移动端事件
    不支持冒泡的事件
    Gulp
    JAVAWEB项目Tomcat与内网穿透实现外网访问,可连接mysql数据库
    Echarts连接Mysql使用心得
    layui的date组件在弹窗里闪退的解决办法
    Layui的table标签使用记录
    Layui后台实现页面内部的iframe跳转
    第16周作业
  • 原文地址:https://www.cnblogs.com/zhangzonghua/p/12849196.html
Copyright © 2020-2023  润新知