HDIS-Framework
HDIS-Framework是一个基于SpringBoot、Kubernetes、阿里云服务,编写的一个用于支撑微服务的极速开发框架。
其文档详尽,Demo全面,设计合理,开箱即用,节省开发时间,提升开发效率。
配套的docker、Kubernetes教程已踩过各种坑,让你的微服务无障碍的顺畅运行起来。
HDIS与Kubernetes或SpringCloud配合使用,能达到最佳效果。
代理与动态代理
这里只阐述自己对代理与动态代理使用场景的理解,其他的信息自行百度。
代理的使用场景?
例子:事务
在项目中,我的service只想处理与业务相关的逻辑。我并不想在service中显示的嵌入代码去处理事务方面的问题,这样事务就和业务耦合在一起了。但是事务的处理是必不可少的,这个时候就可以使用代理模式,将事务的处理放在代理中,代理处理事务的问题,service处理业务的问题。当程序调用代理的时候,既做了代理做的事,同时代理也调用service做了service该做的事。
代理的定义:为其他对象提供一种代理以控制对这个对象的访问。
可以这样思考,方便理解代理模式的使用场景:
什么时候需要使用AOP什么时候就是需要使用代理模式,AOP所做的事情就是代理模式所关注的事情。
如:权限,事务,日志,数据验证,缓存机制等等。
代理模式的简单实现,便于理解。
//接口
public interface 接口{
//操作
publicvoid operation();
}
//实现类
public class 实现类 implement 接口{
@Override
public void operation() {
//一些操作
System.out.println("一些操作");
}
}
//代理类
public class 代理类 implement 接口{
实现类 realObject = new 实现类();
@Override
public void operation() {
//调用目标对象之前可以做相关操作
System.out.println("before");
realObject.operation();
//调用目标对象之后可以做相关操作
System.out.println("after");
}
}
为什么要使用动态代理?
至于为什么需要使用动态代理,我们从反面设想,不使用动态代理,那么就使用普通代理模式,普通代理模式的特点一对一,一个原始类,一个代理类,如果有N多个原始类,就有N多个代理类,可见原来Jive源码中是这样,结果造成代码琐碎,比如权限代理,要为每个原始类都建立一个其实内部内容都差不多的代理类。
那么动态代理正好解决这个问题,只要建立一个权限动态代理类,就能够为多个原始类进行代理。
JDK实现动态代理
JDK的动态代理机制只能代理实现了接口的类,而不能实现接口的类就不能实现JDK的动态代理。
如何使用JDK动态代理?
/**
* 实现自己的InvocationHandler
*/
public class MyInvocationHandler implements InvocationHandler {
// 目标对象
private Object target;
/**
* 构造方法
* @param target 目标对象
*/
public MyInvocationHandler(Object target) {
super();
this.target = target;
}
/**
* 执行目标对象的方法
*/
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 在目标对象的方法执行之前简单的打印一下
System.out.println("------------------before------------------");
// 执行目标对象的方法
Object result = method.invoke(target, args);
// 在目标对象的方法执行之后简单的打印一下
System.out.println("-------------------after------------------");
return result;
}
/**
* 获取目标对象的代理对象
* @return 代理对象
*/
public Object getProxy() {
return Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),
target.getClass().getInterfaces(), this);
}
}
/**
* 目标对象实现的接口,用JDK来生成代理对象一定要实现一个接口
*/
public interface UserService {
/**
* 目标方法
*/
public abstract void add();
}
/**
* 目标对象
*/
public class UserServiceImpl implements UserService {
public void add() {
System.out.println("--------------------add---------------");
}
}
/**
* 动态代理测试类
*/
public class ProxyTest {
@Test
public void testProxy() throws Throwable {
// 实例化目标对象
UserService userService = new UserServiceImpl();
// 实例化InvocationHandler
MyInvocationHandler invocationHandler = new MyInvocationHandler(userService);
// 根据目标对象生成代理对象
UserService proxy = (UserService) invocationHandler.getProxy();
// 调用代理对象的方法
proxy.add();
}
}
执行结果
------------------before------------------
--------------------add---------------
-------------------after------------------
JDK动态代理实现原理?
具体可参考:http://rejoy.iteye.com/blog/1627405
CGLIB实现动态代理
JDK的动态代理机制只能代理实现了接口的类,而不能实现接口的类就不能实现JDK的动态代理。
CGLIB是针对类来实现代理的,他的原理是对指定的目标类生成一个子类,并覆盖其中方法实现增强,但因为采用的是继承,所以不能对final修饰的类进行代理。
CGLIB包的底层是通过使用一个小而快的字节码处理框架ASM(Java字节码操控框架),来转换字节码并生成新的类,其原理是通过字节码技术为一个类创建子类,并在子类中采用方法拦截的技术拦截所有父类方法的调用,顺势织入横切逻辑。
如何使用CGLIB实现动态代理?
public class BookFacadeImpl {
public void addBook() {
System.out.println("增加图书的普通方法...");
}
}
/**
* 使用cglib动态代理
*/
public class BookFacadeCglib implements MethodInterceptor {
private Object target;
/**
* 创建代理对象
*
* @param target
* @return
*/
public Object getInstance(Object target) {
this.target = target;
Enhancer enhancer = new Enhancer();
//设置需要创建子类的类
enhancer.setSuperclass(this.target.getClass());
// 回调方法
enhancer.setCallback(this);
//通过字节码技术动态创建子类实例,创建代理对象
return enhancer.create();
}
@Override
// 回调方法
public Object intercept(Object obj, Method method, Object[] args,
MethodProxy proxy) throws Throwable {
System.out.println("事物开始");
//通过代理类调用父类中的方法
proxy.invokeSuper(obj, args);
System.out.println("事物结束");
return null;
}
}
public class TestCglib {
public static void main(String[] args) {
//动态代理对象
BookFacadeCglib cglib=new BookFacadeCglib();
//通过生成子类的方式创建代理类
BookFacadeImpl bookCglib=(BookFacadeImpl1)cglib.getInstance(new BookFacadeImpl());
//执行代理方法
bookCglib.addBook();
}
}