动态代理
动态代理从大的讲是动态语言特性,JAVA作为需要编译才能运行的静态语言,动态代理机制可以为JAVA提供在运行态时对某些对象进行功能增强,Spring中如果有对象使用了AOP相关注解,那么在bean进行实例化后会将对应的动态代理对象放在bean工厂,动态代理有2种实现方式:实现JDK原生动态代理接口,或者使用cglib实现,在默认情况下 Spring AOP 会采用 Java 动态代理实现,而当该类没有对应接口时才会使用 CGLib 动态代理实现。
jdk动态代理
该种动态代理的实现前提是被代理的对象实现了某个接口,代理对象将被强制转换成接口实现,通过调用该接口实现方法完成功能增强;
如下TestService是个公共的接口方法,OrderServer实现了该方法,它是被代理的对象,OrderServerProxy是代理对象,通过java的反射包里面的()方法,再强转成接口的实现,创建1个接口:
public interface TestService {
void sell();
}
- 1
- 2
- 3
实现该接口的实现类(被代理对象):
@Service
public class OrderServer implements TestService {
@Override
public void sell(){
System.out.println("begin to sell something.");
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
实现动态代理接口的代理类(代理对象):
public class OrderServerProxy implements InvocationHandler {
private Object object;
public OrderServerProxy(Object object) {
this.object = object;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("do something before.");
return method.invoke(object,args);
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
测试方法和输出:
@GetMapping("/test/proxy")
public void test1(){
OrderServer orderServer = new OrderServer();
TestService testService = (TestService) Proxy.newProxyInstance(orderServer.getClass().getClassLoader(), orderServer.getClass().getInterfaces(), new OrderServerProxy(orderServer));
testService.sell();
}
- 1
- 2
- 3
- 4
- 5
- 6
do something before.
begin to sell something.
- 1
- 2
cglib实现代理
(Code Generation Library)该种代理方式是采用了开源的字节码工具ASM完成,它不需要被代理对象继承某个接口,在实现上直接把代理对象作为被代理对象的子类,首先引入cglib的pox依赖:
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>2.2.2</version>
</dependency>
- 1
- 2
- 3
- 4
- 5
- 6
创建一个被代理对象,这个被代理对象不需要实现某个接口:
@Service
public class OrderServer2 {
public void sell(){
System.out.println("begin to sell something.");
}
}
- 1
- 2
- 3
- 4
- 5
- 6
创建代理对象,实现拦截器方法:
public class ServiceInterceptor implements MethodInterceptor {
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("do something in cglib interceptor...");
methodProxy.invokeSuper(o, objects);
return o;
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
测试和输出:
@GetMapping("/test/cglib")
public void test2(){
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(OrderServer2.class);
enhancer.setCallback(new ServiceInterceptor());
OrderServer2 orderServer2 = (OrderServer2) enhancer.create();
orderServer2.sell();
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
do something in cglib interceptor...
begin to sell something.
- 1
- 2
反射机制
java中的反射机制能够让开发者在程序运行态中获取到已经被实例化的bean中的属性和方法,甚至能够修改其中的属性值和方法实现,所以反射是动态代理的基础,比如上面的().getClassLoader()和().getInterfaces()分别是获取已经被实例化的orderServer对象的的类加载器和实现的接口列表,orderServer是1个已经被放在堆内存中的对象;