java中的代理模式

一、什么是代理模式

代理模式:为其他对象提供一种代理以控制对这个对象的访问。
好处:可以控制被代理类的访问和行为。在不修改被代理类的情况下对被代理类的访问做出修改。

二、代理分类

代理分为:

静态代理:编译期已经确定了被代理的对象和代理类。
  • 代理类和被代理类实现同样的接口(保证行为一致)
  • 代理类持有一个被代理类对象(保证代理类能够调用到被代理类)
动态代理:在运行期间才确定被代理的对象,并动态生成一个代理类。
三、静态代理

就用一个简单的例子来介绍静态代理吧,比如清朝皇帝溥仪被太后慈禧操控,垂帘听政,这里被代理人就是溥仪,而代理人就是慈禧
① 先写一个King接口

package proxy.staticproxy;

public interface King {
    void shangchao();	// 上朝
    void pingshen();	// 平身
}

② 慈禧实现King接口

package proxy.staticproxy;

import java.util.Random;

public class CiXi implements King {
    private FuYi fuYi;

    public CiXi(FuYi fuYi) {
        this.fuYi = fuYi;
    }

    @Override
    public void shangchao() {
        Random rd = new Random();
        int i = rd.nextInt(10);
        System.out.println(i);
        if(i%2==1){
            fuYi.shangchao();
        }else{
            System.out.println("太后上朝");
        }
    }

    @Override
    public void pingshen() {
        fuYi.pingshen();
    }
}

③ 溥仪实现King接口

package proxy.staticproxy;

public class FuYi implements King {
    @Override
    public void shangchao() {
        System.out.println("皇帝上朝!");
    }

    @Override
    public void pingshen() {
        System.out.println("众卿平身!");
    }
}

④ 编写测试类

package proxy.staticproxy;

public class Test {
    public static void main(String[] args) {
        // 静态代理
        FuYi fuYi = new FuYi();
        // 慈禧代理
        King king = new CiXi(fuYi);
        king.shangchao();
        king.pingshen();
	}
}

⑤ 运行结果
在这里插入图片描述

四、动态代理

Java中动态代理有两种:

Jdk动态代理:通过反射来创建代理类。被代理类和代理类实现同样的接口。(必须有共同的接口)
  • 实现共同的接口,需要定义一个共同的接口。
  • 需要定义代理类的回调类,该类需要实现InvokecationHandler接口,在invoke方法中编写代理类的逻辑
  • 需要通过反射的API,生成代理类。
Cglib动态代理:通过编辑字节码文件来生成一个代理类。生成的代理类继承自被代理类。
  • 导入cglib依赖
  • 实现MethodInterceptor接口

代理类和被代理类如何保证行为一致?

  • 实现同样的接口
  • 继承关系
Jdk动态代理

① 创建被代理接口

package proxy;

import entity.Admin;
import org.apache.ibatis.annotations.Delete;
import org.apache.ibatis.annotations.Select;

public interface AdminMapper {
    @Delete("delete from t_admin where id=#{id}")
    int delete(Integer id);

    @Select("select id,name,phone from t_admin where id=#{id}")
    Admin selectById(Integer id);
}

② 创建生成代理类的类

public class MapperProxy implements InvocationHandler {
    public Object getMapper(Class mapperClass){
        return Proxy.newProxyInstance(
                mapperClass.getClassLoader(), // 被代理类的类加载器
                new Class[]{mapperClass},   // 被代理类实现的接口
                this    // InvocationHandler对象
        );
    }

	/**
     * 回调方法,在调用代理类的方法时会触发该方法
     * @param proxy 代理对象
     * @param method 调用的方法
     * @param args  方法参数
     * @return
     * @throws Throwable
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    // 这里写的是一些业务逻辑
    	//        Delete annotation = method.getAnnotation(Delete.class);
//        if(annotation!=null){
//            String[] s = annotation.value();
//            String sql = s[0];
//            sql = sql.replaceAll("#\\{\\w+\\}", "?");
//            System.out.println(sql);
//            Connection connection = null;
//            PreparedStatement ps = null;
//            int res = 0;
//            try {
//                Class.forName("oracle.jdbc.driver.OracleDriver");
//                connection = DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:XE", "blog", "123456");
//                ps = connection.prepareStatement(sql);
//                for (int i = 0; i < args.length; i++) {
//                    ps.setObject(i+1, args[i]);
//                }
//                res = ps.executeUpdate();
//                // 事务提交
//                connection.commit();
//            } catch (ClassNotFoundException e) {
//                e.printStackTrace();
//            } catch (SQLException e) {
//                e.printStackTrace();
//                connection.rollback();
//            } finally {
//                ps.close();
//                connection.close();
//            }
//            return res;
//        }
//        return null;
    }
}

③ 编写测试类

public class Test {
    public static void main(String[] args) throws IOException {
    	// 通过传入Class对象动态的生成代理类
        AdminMapper mapper = (AdminMapper) new MapperProxy().getMapper(AdminMapper.class);
        // 调用delete方法后会自动调用invoke方法并执行其中的业务逻辑
        mapper.delete(5);
    }
}
Cglib动态代理

① 在maven项目中导入cglib依赖

<dependency>
      <groupId>cglib</groupId>
      <artifactId>cglib</artifactId>
      <version>3.2.12</version>
</dependency>

② 创建生成代理类的类

package proxy.cglib;

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;


import java.lang.reflect.Method;

public class CglibProxy implements MethodInterceptor {
    private Object obj;	// 存储被代理对象

    // 生成代理对象
    public Object getProxy(Object obj){
        this.obj = obj;
        return Enhancer.create(
                obj.getClass(), // 被代理对象
                this    // MethodInterceptor接口类实现对象
        );
    }


    /**
     * 代理对象调用方法的时候触发
     * @param o 代理对象
     * @param method 执行的方法
     * @param objects 参数
     * @param methodProxy 代理方法
     * @return
     * @throws Throwable
     */
    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        String name = method.getName();
        if(name.startsWith("set")){
            System.out.println("set方法不允许操作!");
            return null;
        }
        // 执行方法,通过代理方法调用被代理的方法
        Object o1 = method.invoke(obj, objects);
        return o1;
    }

}

③ 编写测试类

package proxy.cglib;

import entity.Admin;

public class Test {
    public static void main(String[] args) {
        Admin admin = new Admin(1, "admin", "111", "tom", "222", "333", "1", "男");
        Admin proxy = (Admin) new CglibProxy().getProxy(admin);
        proxy.setName("lala");
        System.out.println(proxy.getName());
    }
}

④ 运行结果
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值