Java_动态代理_proxy

一、动态代理

动态代理就是在程序运行期间,创建代理对象,并对目标对象中的方法进行功能增强的一种手段。
在生成代理对象的过程中,目标对象不变,代理对象中的方法就是目标对象中的方法的增强。
也可以说,代理对象将目标对象执行的方法拦截,在目标对象方法执行的前后先执行一些增强方法。
使用JDK提供的动态代理方法:使用Proxy类创建代理对象。

        HMan hMan = new HMan();
//        目标对象:需要增强的对象
//        参数一:目标对象的类加载器对象
//        参数二:目标对象的接口字节码对象
//        参数三:调用处理器,代理对象中的方法被调用,都会在执行方法时对所有被代理对象的方法进行拦截
//代理对象其实就是接口类的子类
Man proxyMan = (Man)Proxy.newProxyInstance(HMan.class.getClassLoader(), new Class[]{Man.class}, new InvocationHandler() {
            @Override
//            代理对象每次调用目标对象方法时都会执行invoke
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            //表示当调用代理对象时首先判断使用的方法如果是married则进行增强。如果不是则让(hman对象自己调用自己的方法,也就是不增强hman目标对象的其他方法)
                if (method.getName().equals("married")) {
//                    此处的invoke是反射的,反射方法的invoke需要传入参数才可以执行
                    Object o = method.invoke(hMan, args);
                    System.out.println("再娶一个");
                    //这个return是返回给 public Object invoke()这个方法的,因为代理对象每次调用方法都会调用invoke(),而有些方法是有返回值的,若是不返回就会是一个空值
                    return o;
                }
                return  method.invoke(heNanMan, args);
            }
        });

接口:

public interface Man {
    void drink();
    void eat();
    void married();
    void makeMoney();
}

实现接口的实现类:

public class HMan implements Man{
    @Override
    public void eat() {
        System.out.println("吃面");
    }

    @Override
    public void drink() {
        System.out.println("he汤");
    }

    @Override
    public void makeMoney() {
        System.out.println("赚钱");
    }

    @Override
    public void married() {
        System.out.println("先娶一个");
    }
}

附上其他代理对象的使用实例(日志文件logback):
使用properties文件表示用户设置的等级:

level=warn
file=d:/a.log

Logger接口:

public interface Logger {
    void debug(String debug);
    void info(String info);
    void warn(String warn);
    void error(String error);
    void fatal(String fatal);
}

LogbackFactory:

import sun.rmi.runtime.Log;

import java.io.*;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

public class LogbackFactory {

    private static Properties properties = new Properties();
    private static Map<String,Integer> map = new HashMap<>();
    static{
        InputStream in = LogbackFactory.class.getClassLoader().getResourceAsStream("loggback.properties");
        try {
            properties.load(in);
        } catch (IOException e) {
            e.printStackTrace();
        }
        //给不同的错误设置等级,用来设置什么等级以上或者等于这个等级才可以被存入日志
        map.put("debug",1);
        map.put("info",2);
        map.put("warn",3);
        map.put("error",4);
        map.put("fatal",5);
    }
//调用LogbackFactor中的Logger方法获得一个Logger的代理对象
    public static Logger getLogger(Class clazz){
    //对Logger接口对象(目标对象)进行了加强
        return (Logger) Proxy.newProxyInstance(clazz.getClassLoader(),
                new Class[]{Logger.class},
                new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                //根据配置文件级别输出日志
                //1.拿到用户配置的级别
                String level1 = properties.getProperty("level");
                Integer num1 = map.get(level1);
                //2.拿到方法的级别
                String level2 = method.getName();
                Integer num2 = map.get(level2);
                if (num2 >= num1) {
                    //将日志文件写入硬盘,字符缓冲流
                    BufferedWriter bw = new BufferedWriter(new FileWriter(properties.getProperty("file")));
                    SimpleDateFormat sd = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                    String time = sd.format(new Date());
                    System.out.println(time + "\t" + clazz.getName() + "\t" + args[0]);
                    bw.write(time + "\t" + clazz.getName() + "\t" + args[0]);
                    bw.newLine();
                    bw.close();
                }
                return null;
            }
        });
    }
}

测试类:

public class LoggerTest {
//获得代理对象logger
   private static Logger logger = LogbackFactory.getLogger(LoggerTest.class);
  
    public static void main(String[] args) {
          //logger.warn("warn");
          //代理对象调用方法时,就会执行invoke方法进行增强
          logger.debug("debug");
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值