新手小白记录跟着狂神学Spring的过程(第19集)~
1. 浅谈AOP
AOP(面向切面编程)的底层就是动态代理,它把「通用的额外操作」(例如日志、事务、权限)抽成切面(Aspect),然后通过动态代理,自动把切面逻辑织入到业务方法中。
2. 代理调用处理程序类
作用:可以通过这个类自动生成一个代理类。
这个类实现了InvocationHandler接口,其中,最关键的方法是invoke(),这个方法在调用代理方法时执行,可以把日志等需要处理的方法放在invoke()里面。这样,当调用代理方法时,也会执行日志记录这个方法。并且,invoke 是 JVM 自动调用的:你不用手动写 handler.invoke(...),JVM 会帮你做这个动作,这也是动态代理的核心便捷性。
public class ProxyInvocationHandler implements InvocationHandler{
//被代理的对象
private Object target;
public void setTarget(Object target){
this.target = target;
}
// 生成代理实例
public Object getProxy(){
return Proxy.newProxyInstance(
this.getClass().getClassLoader(),
target.getClass().getInterfaces(),
this
);
}
// invoke方法:这里是代理逻辑的定义,可以在这里加上打印日志等方法
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
log(method.getName());
Object result = method.invoke(target, args);
return result;
}
// 打印日志
public void log(String msg){
System.out.println("执行了" + msg + "方法");
}
3. 如何动态生成代理类
@Test
public void test(){
// 被代理的角色
UserService userService = new UserServiceImpl();
// 等会要用代理调用处理程序动态生成代理类
ProxyInvocationHandler pih = new ProxyInvocationHandler();
// 设置要代理的对象
pih.setTarget(userService);
//动态生成代理类
UserService proxy = (UserService)pih.getProxy();
//调用代理方法
proxy.add();
}
4.JDK动态代理代理的是接口
由于Java 的语法规则是:一个类只能有一个直接父类(单继承)。既然代理类已经继承了 Proxy,就无法再继承目标类(比如 UserServiceImpl)—— 只能通过「实现目标类的接口」(比如 UserService),来和目标对象建立方法关联。
JDK 动态代理的核心方法 Proxy.newProxyInstance,必须传入目标对象的接口数组(Class<?>[] interfaces),底层会根据这些接口生成代理类的字节码:
- 代理类会implements这些接口,并重写接口中的所有方法;
- 重写后的方法内部,会调用
InvocationHandler的invoke方法。
所以,jdk的代理对象是一个接口。