动态代理的作用:目标方法代码不修改,为其添加功能。
动态代理底层涉及知识点:反射,类加载器,可以参考博客反射、类对象和类加载器_source code August的博客-CSDN博客
前言Spring的AOP,可以理解为动态代理实现的一种规范化,因为我们自己实现动态代理可以使用JDK动态代理,也可以使用CGLIB动态代理。这两种都是Spring AOP的底层实现原理,使用场景:
若目标对象实现了接口,spring默认使用JDK的动态代理。
优点:因为有接口,所以使系统更加松耦合
缺点:为每一个目标类创建接口
若目标对象没有实现任何接口,spring使用CGLIB进行动态代理。
优点:因为代理类与目标类是继承关系,所以不需要有接口的存在。
缺点:因为没有使用接口,所以系统的耦合性没有使用JDK的动态代理好。
若目标对象实现了接口,但是强制cglib代理,则使用cglib代理
JDk动态代理的代码实现1.目标对象SomeService。(JDK动态代理要求目标对象必须实现接口)
2.InvocationHandler接口实现
3.测试类
4.输出结果
5.原理分析
1.目标对象SomeService//定义目标接口
public interface SomeService {
public void doSome();
public void doOther();
}
//定义目标实现类
public class SomeServiceImpl implements SomeService {
@Override
public void doSome() {
System.out.println("doSome");
}
@Override
public void doOther() {
System.out.println("domeOther");
}
}
2.InvocationHandler接口实现
public class MyInvocationHandler implements InvocationHandler {
//动态代理的目标对象
private Object target;
//构造方法,在new InvocationHandler的时候传入目标类对象
public MyInvocationHandler(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//通过代理对象执行方法时,会调用执行这个invoke()
Object res=null;
//如果代理类对象执行的是doSome才进行功能增强。
if (method.getName().equals("doSome")){
System.out.println("在doSome之前执行");
//执行目标类的方法,通过method类执行invoke方法实现
res=method.invoke(target,args);
System.out.println("在doSome之后执行");
}else {
res=method.invoke(target,args);
}
return res;
}
}
3.测试类
public class Test {
public static void main(String[] args) {
SomeService someService = new SomeServiceImpl();
MyInvocationHandler myInvocationHandler = new MyInvocationHandler(someService);
//使用proxy创建代理,newProxyInstance是静态方法,可以直接"类名.方法"使用,第二个参数是获取有哪些接口方法
Object o = Proxy.newProxyInstance(someService.getClass().getClassLoader(), someService.getClass().getInterfaces(), myInvocationHandler);
//上面Object可以使用强转,为SomeService
SomeService proxy=(SomeService) o;
//通过代理执行方法,会调用handler中的invoke()
proxy.doSome();//调用doSome方法
}
}
4.输出结果
测试类执行doSome
测试类执行doOther
通过代理,实现了在不修改目标类方法代码的情况下,通过代理执行目标类方法,在目标类方法执行的时候,为其增加了功能。比如这里的"在domeSome之前执行" 和“在domeSome之后执行”就是增加的功能。这些增加的代码,就是我们常说的"切面"。
关于详细的Spring AOP使用可以参考博客“https://正在连载”
5.原理分析动态代理底层涉及知识点:反射,类加载器,可以参考博客反射、类对象和类加载器_source code August的博客-CSDN博客
为什么JDK动态代理要求目标对象必须实现接口?可以发现前面创建的代理类对象进行了强制类型转换,SomeService proxy=(SomeService) o;代理对象需要强制类型转化为目标类才可以调用目标类的方法。关于强制类型转化的理解可以参考:Java强制类型转化和自动类型转化_source code August的博客-CSDN博客
连载中...



