一、动态代理
动态代理就是在程序运行期间,创建代理对象,并对目标对象中的方法进行功能增强的一种手段。
在生成代理对象的过程中,目标对象不变,代理对象中的方法就是目标对象中的方法的增强。
也可以说,代理对象将目标对象执行的方法拦截,在目标对象方法执行的前后先执行一些增强方法。
使用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");
}