JDK动态代理 对“装饰者”设计模式简化。使用前提:必须有接口。组成部分:
1.目标类:接口 + 实现类 ;
2.切面类:用于存通知 MyAspect;
3.工厂类:编写工厂生成代理;
4.测试。
按照步骤我们首先目标类得接口:
public interface UserService {
public void addUser();
public void updateUser();
public void deleteUser();
}
定义实现:
public class UserServiceImpl implements UserService {
@Override
public void addUser() {
System.out.println("add User");
}
@Override
public void updateUser() {
System.out.println("update User");
}
@Override
public void deleteUser() {
System.out.println("delete User");
}
}
然后编写切面类:
public class MyAspect {
public void before() {
System.out.println("鸡首");
}
public void after() {
System.out.println("牛后");
}
}
继而编写工厂生成代理:
public class MyBeanFactory {
public static UserService createService() {
//1 目标类
final UserService userService = new UserServiceImpl();
//2切面类
final MyAspect myAspect = new MyAspect();
/* 3 代理类:将目标类(切入点)和 切面类(通知) 结合 --> 切面
* Proxy.newProxyInstance
* 参数1:loader ,类加载器,动态代理类 运行时创建,任何类都需要类加载器将其加载到内存。
* 一般情况:当前类.class.getClassLoader();
* 目标类实例.getClass().get...
* 参数2:Class[] interfaces 代理类需要实现的所有接口
* 方式1:目标类实例.getClass().getInterfaces() ;注意:只能获得自己接口,不能获得父元素接口
* 方式2:new Class[]{UserService.class}
* 例如:jdbc 驱动 --> DriverManager 获得接口 Connection
* 参数3:InvocationHandler 处理类,接口,必须进行实现类,一般采用匿名内部
* 提供 invoke 方法,代理类的每一个方法执行时,都将调用一次invoke
* 参数31:Object proxy :代理对象
* 参数32:Method method : 代理对象当前执行的方法的描述对象(反射)
* 执行方法名:method.getName()
* 执行方法:method.invoke(对象,实际参数)
* 参数33:Object[] args :方法实际参数
*/
UserService proxService = (UserService)Proxy.newProxyInstance( MyBeanFactory.class.getClassLoader(), userService.getClass().getInterfaces(), new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//前执行
myAspect.before();
//执行目标类的方法
Object obj = method.invoke(userService, args);
//后执行
myAspect.after();
return obj;
}
});
return proxService;
}
}
测试:
public class Main {
public static void main(String[] args) {
UserService userService = MyBeanFactory.createService();
userService.addUser();
userService.updateUser();
userService.deleteUser();
}
}
执行结果:
public interface UserService {
public void addUser();
public void updateUser();
public void deleteUser();
}
对代码进行断点,可以看到其返回的是JDK的动态代理(其后面的数字每次是变化的):
image.png
完毕。
网上有篇文章描述JDK源码得分析,写得不错地址:https://www.jianshu.com/p/00af91a7c838。
先建立接口:
public interface UserService {
void query();
}
然后实现这个接口:
public class UserServiceImpl implements UserService {
public void query() {
System.out.println("查询用户信息");
}
}
定义一个类,需要实现InvocationHandler:
public class MyInvocationHandler implements InvocationHandler {
Object target;
public MyInvocationHandler(Object target) {
this.target = target;
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("进入了invoke");
method.invoke(target);
System.out.println("执行了invoke");
return null;
}
}
然后就是Main方法了:
public class Main {
public static void main(String[] args) {
MyInvocationHandler myInvocationHandler = new MyInvocationHandler(new UserServiceImpl());
Object o = Proxy.newProxyInstance(Main.class.getClassLoader(),
new Class[]{UserService.class}
, myInvocationHandler);
((UserService)o).query();
}
}
运行结果:
进入了invoke
查询用户信息
执行了invoke
一切正常,成功的执行了增强的逻辑,也执行了目标方法。