Spring的动态代理有两种实现方式:JDK的动态代理;cglib的动态代理。
JDK的代理方式只能代理实现了接口的类,而不能实现接口的类就不能实现JDK的动态代理。这就要使用cglib动态代理了。这里主要聊聊JDK的动态代理。
说到动态代理,就不得不说代理模式。
一:代理模式
使用代理模式必须要让代理类和目标类实现相同的接口,客户端通过代理类来调用目标方法,代理类会将所有的方法调用分派到目标对象上反射执行,还可以在分派过程中添加"前置通知"和后置处理(如在调用目标方法前校验权限,在调用完目标方法后打印日志等)等功能。
二:使用动态代理的四大步骤
1.通过实现InvocationHandler接口来自定义自己的InvocationHandler;
2.将被代理对象作为参数传递给自定义的InvocationHandler实例对象的构造参数
3.通过Proxy.newProxyInstance获得动态代理类
4.通过代理对象调用目标方法
三:实践
目的:通过动态代理实现AOP的横切加入日志操作
1·定义接口:UserMgr
package com.dynamic.aop.proxy;
/**
* 用户管理 接口
* @author 贾丽敏
*
*/
public interface UserMgr {
void addUser();
void delUser();
}
2·定义实现类
package com.dynamic.aop.proxy;
public class UserMgrImpl implements UserMgr {
public void addUser() {
System.out.println("----添加用户--------");
}
public void delUser() {
System.out.println("----删除用户--------");
}
}
3·自定义日志处理类并实现InvocationHandler接口:
package com.dynamic.aop.proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
/**
* 日志操作处理
* @author 贾丽敏
*
*/
public class LoggingHandler implements InvocationHandler {
//被代理对象
private Object target;
public LoggingHandler(Object target){
super();
this.target=target;
}
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
System.out.println("开始日志记录..........");
Object object = method.invoke(target, args);
System.out.println("结束日志记录..........");
return object;
}
}
4·客户端:
public static void main(String[] args){
UserMgr ug=new UserMgrImpl();
//为用户管理添加日志记录操作
LoggingHandler loghandler=new LoggingHandler(ug);
//生成代理对象
ClassLoader loader=UserMgr.class.getClassLoader();
Class[] interfaces=new Class[]{UserMgr.class};
//代理对象的类型,即其中有哪些方法
UserMgr proxy = (UserMgr)Proxy.newProxyInstance(loader, interfaces, loghandler);
proxy.addUser();
System.out.println("----------------------分界线-------------");
proxy.delUser();
}
执行结果: