共计 2609 个字符,预计需要花费 7 分钟才能阅读完成。
摘要
- 别离演示动态代理和动静代理
动态代理
手动代理
interface
public interface Interface_ {public void do(); | |
} |
须要被增强的类
public class Object_ implements Interface_{ | |
@Override | |
public void do() {System.out.println("do"); | |
} | |
} |
代理类
public class Object_Agent implements Interface_{ | |
private Object_ object_; | |
public Object_Agent(Object_ object_) {this.object_ = object_;} | |
@Override | |
public void do() {System.out.println("enhance"); | |
object_.do();} | |
public static void main(String[] args) {Object_ object_ = new Object_(); | |
Object_Agent agent = new Object_Agent(object_); | |
agent.do();} | |
} |
AspectJ 动态
- 编写形式和 spring aop 没有区别
- Aspectj 并不是动静的在运行时生成代理类,而是在编译的时候就植入代码到 class 文件
- 因为是动态织入的,所以性能相对来说比拟好
动静代理
- JDK 动静代理是基于接口的形式,代理类和指标类都实现同一个接口。
- CGLib 动静代理是代理类去继承指标类,而后重写其中指标类的办法。
JDK 动静代理
接口
public interface Interface_ {public void do(); | |
} |
须要被增强的类
public class Object_ implements Interface_{ | |
@Override | |
public void do() {System.out.println("do"); | |
} | |
} |
处理器实现类
public class InvocationHandlerImpl implements InvocationHandler{ | |
private Object object; | |
public InvocationHandlerImpl(Object object) | |
{this.object = object;} | |
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable | |
{System.out.println("enhance"); | |
Object object = method.invoke(object, args); | |
return object; | |
} | |
} |
测试
public class DynamicProxyDemonstration | |
{public static void main(String[] args) | |
{Interface_ object_ = new Object_(); | |
InvocationHandler handler = new InvocationHandlerImpl(object_); | |
ClassLoader loader = object_.getClass().getClassLoader(); | |
Class[] interfaces = object_.getClass().getInterfaces(); | |
Interface_ object__ = (Interface_) Proxy.newProxyInstance(loader, interfaces, handler); | |
object__.do();} | |
} |
CGlib 动静代理
POM
<dependency> | |
<groupId>cglib</groupId> | |
<artifactId>cglib</artifactId> | |
<version>2.2.2</version> | |
</dependency> |
须要被增强的类
public class Object_{public void do() {System.out.println("do"); | |
} | |
} |
办法拦截器
public class MyMethodInterceptor implements MethodInterceptor{ | |
@Override | |
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {System.out.println("enhance"); | |
Object object = proxy.invokeSuper(obj, args); | |
return object; | |
} | |
} |
测试
public class CgLibProxy {public static void main(String[] args) { | |
// 创立 Enhancer 对象,相似于 JDK 动静代理的 Proxy 类,下一步就是设置几个参数 | |
Enhancer enhancer = new Enhancer(); | |
// 设置指标类的字节码文件 | |
enhancer.setSuperclass(Object_.class); | |
// 设置回调函数 | |
enhancer.setCallback(new MyMethodInterceptor()); | |
// 创立加运行 | |
Object_ proxyObject_ = (Object_)enhancer.create(); | |
proxyObject_.do();} | |
} |
为啥转变被 CGlib
个别写代码:
@Autowired | |
UserService userService; |
出错代码:
@Autowired | |
UserServiceImpl userService; |
JDK 动静代理是基于接口的,代理生成的对象只能赋值给接口变量。
而 CGLIB 就不存在这个问题。因为 CGLIB 是通过生成子类来实现的,代理对象无论是赋值给接口还是实现类这两者都是代理对象的父类。
总结
- Spring5 默认 aop 实现为 CGlib
- JDK 动静代理是基于接口的,CGlib 动静代理是基于继承的
参考
[1].CGLib 动静代理
[2].java 反射和代理
[3]. 惊人!Spring5 AOP 默认应用 Cglib? 从景象到源码深度剖析
本文作者: Both Savage
本文链接: https://bothsavage.github.io/…
版权申明: 本博客所有文章除特地申明外,均采纳 BY-NC-SA 许可协定。转载请注明出处!
正文完