时间不够就看这两句话
有接口jdk动态代理,没接口cglib动态代理。
aop时加载所有切面类,拿到切点和本类的方法一一比较,匹配到了执行动态代理。
一、动态代理
AOP中最最核心的一点就是动态代理,动态代理就是帮助我们扩展现有功能的,那么动态代理怎么实现呢?
1、jdk动态代理
jdk动态代理是代理实现的一种方式,这种方式适用于使用接口的形式。
主要是这几步:创建接口、生成接口实现类、创建代理逻辑的类、测试。
(1)创建接口
public interface HelloWorld {
public void sayHello();
}
(2)创建接口实现类
public class HelloWorldImpl implements HelloWorld{
public void sayHello() {
System.out.println("Hello World");
}
}
(3)创建代理逻辑的类,实现invoke方法,这里面写代理逻辑,也就是扩展原来的方法。
public class JdkProxyExample implements InvocationHandler {
//创建真实对象
private Object target = null;
//建立代理对象和真实对象的联系
public Object bind(Object target){
this.target = target;
return Proxy.newProxyInstance
(target.getClass().getClassLoader(),target.getClass().getInterfaces(),this);
}
//代理方法逻辑
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("进入代理逻辑");
System.out.println("调度真实对象之前的服务");
Object obj = method.invoke(target, args);
System.out.println("调度真实对象之后的服务");
return obj;
}
}
测试。
public class testJdkProxy {
public static void main(String[] args) {
JdkProxyExample jdk = new JdkProxyExample();
HelloWorld proxy = (HelloWorld) jdk.bind(new HelloWorldImpl());
proxy.sayHello();
}
}
2、cglib动态代理
实际上也有不含接口的类,这些怎么实现动态代理呢?这就需要使用cglib动态代理了。
这里使用增强类来实现动态代理,生成代理对象,然后操作代理逻辑。
public class CglibProxyExample implements MethodInterceptor {
//生成代理对象
public Object getProxy(Class cls){
//增强类对象
Enhancer enhancer = new Enhancer();
//设置增强类型
enhancer.setSuperclass(cls);
//定义代理逻辑对象为当前对象
enhancer.setCallback(this);
//生成并返回代理对象
return enhancer.create();
}
//代理逻辑方法
public Object intercept(Object o, Method method,
Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("调用真实对象前");
Object result = methodProxy.invokeSuper(o,objects);
System.out.println("调用真实对象后");
return result;
}
}
测试。
public class testCglibProxy {
public static void main(String[] args) {
CglibProxyExample cpe = new CglibProxyExample();
HelloWorldImpl obj = (HelloWorldImpl) cpe.getProxy(HelloWorldImpl.class);
obj.sayHello();
}
}
二、AOP
aop操作实际上就是使用动态代理来扩展现有的类和方法。
首先我们会在某个类上加上切面@Aspect来定义一个切面,当然这里类上也需要加上@Component注解把这个类加入到容器中。
当某个类A需要使用AOP横向切入了,Spring会看到这个类的上级是否有接口,也就是它是不是某个接口的实现类,如果是的话,Spring会选择jdk动态代理,如果不是则会选择cglib动态代理。
A要创建对象,创建对象的流程如下:
class——>实例化对象——>DI注入——>初始化——>aop(代理对象)——>bean
创建对象走到aop这一步,Spring会拿到所有加上@Aspect的类,找到它们的切点和当前类中的方法进行一一比较,切点因为有表达式,这样很容易定位,如果定位到了,那么就会执行下去。
因为要创建代理对象,代理对象不管是哪种方式,都会先拿到原对象target,然后在代理类中调用target需代理的方法,并在它的前后左右加上代理逻辑。