java提供的动态代理机制是一种强大的语言结构,可以为一个或多个接口创建代理对象而不需要预先拥有一个接口的实现类。Spring的AOP也是建立在java的代理机制之上的,本篇文章通过一个例子简单理解一下java的动态代理机制实现AOP。
本例将通过动态代理来实现日志输出功能:
1、编辑Login接口,提供login()方法用于执行管理员登录操作。
public interface Login {
public void login();
}
2、编辑Login接口的实现类LoginImpl,此类只包含业务逻辑代码,模拟管理员的登录操作。
public class LoginImpl implements Login {
@Override
public void login() {
System.out.println("===========登录==========");
}
}
3、编辑LogProxy,此类实现Java提供的InvocationHandler接口,通过这个代理类,可以在运行时自动创建指定接口的代理对象,并由此对象完成相关业务逻辑流程。
public class LogProxy implements InvocationHandler {
private Object proxyObj;
public LogProxy(Object proxyObj) {
this.proxyObj = proxyObj;
}
//创建代理对象
public static Object bind(Object object) {
Class cls = object.getClass();
return Proxy.newProxyInstance(cls.getClassLoader(), cls.getInterfaces(), new LogProxy(object));
}
//在唯一的切入点的前后执行日志输出
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
login(method);
Object object = method.invoke(proxyObj, args);
logout(method);
return object;
}
//横向关注点,实现输出日志功能
private void logging(String msg) {
System.out.println(msg);
}
private void login(Method method) {
logging("方法" + method.getName() + "执行之前的日志信息");
}
private void logout(Method method) {
logging("方法" + method.getName() + "执行之前的日志信息");
}
}
4、测试类
public class TestLog {
public static void main(String[] args) {
Login login = (Login) LogProxy.bind(new LoginImpl());
login.login();
}
}
5、输出
方法login执行之前的日志信息
===========登录啦==========
方法login执行之前的日志信息
使用面向接口编程和动态代理机制,有效地实现各功能模块之间解耦,用于实现日志记录功能的代码和实现业务逻辑的代码不再相互依赖,只有调用业务逻辑并且记录日志时,二者才产生关联。同时,任何业务逻辑需要加入日志输出功能,只需要通过代理工厂创建一个代理对象即可。