发表于: 2018-09-10 20:59:22
1 508
今天完成的事情:(一定要写非常细致的内容,比如说学会了盒子模型,了解了Margin)
1.代理知识学习
http://www.cnblogs.com/xiaoluo501395377/p/3383130.html
java中的代理技术有很多:jdk,cglib,javassist,ASM等
spring中常用的代理方法
1.jdk自带的jdk 必须有接口
2.cglib 不需要接口
mybaits中使用了javassist
————————————————————————————————————————
jdk代理【必须要有接口】
1.创建一个接口 写个实现类
public interface HelloWorld {
public void sayHelloWorld();
}
public class HelloWorldImpl implements HelloWorld {
@Override
public void sayHelloWorld() {
System.out.println("hello world");
}
}
2.开始动态代理
在jdk中动态代理逻辑需实现invocationHandler接口
public class JdkProxyExample implements InvocationHandler {
//真实对象
private Object target = null;
/**
* TODO 建立代理对象和真实对象的代理关系,并范围代理对象
*
* newProxyInstance方法中三个参数
* 1.类加载器
* 2.代理对象生成后挂在哪个接口下方
* 3.实现方法逻辑的代理类,this表示当前对象
*
* @param target 真实对象
* @return 代理对象
* @date 2018/9/9 20:27
* @author Liu Kai
**/
public Object bind(Object target) {
this.target = target;
return Proxy.newProxyInstance(target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
this);
}
/**
* TODO 代理方法逻辑
*
* @param proxy 代理对象
* @param method 当前调度方法
* @param args 当前方法参数
* @return 代理结果返回
* by Liu Kai 2018/9/10 21:02
**/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("进入代理逻辑方法");
System.out.println("在调度真实对象之前的服务");
Object obj = method.invoke(target, args);//相当于sayHelloWorld()方法
System.out.println("在调度真实对象之后的服务");
return obj;
}
}
测试
public class JdkProxyTest {
public static void main(String[] args) {
JdkProxyExample jdk = new JdkProxyExample();
HelloWorld proxy = (HelloWorld) jdk.bind(new HelloWorldImpl());
proxy.sayHelloWorld();
}
}
控制台输出
进入代理逻辑方法
在调度真实对象之前的服务
hello world
在调度真实对象之后的服务
————————————————————————————————————————
2.cglib代理 不需要接口
@Slf4j
public class CglibProxyExample implements MethodInterceptor {
/**
* TODO 生成cglib代理对象
* @param cls class类
* @return class类的cglib代理对象
* by Liu Kai 2018/9/10 21:15
**/
public Object getProxy(Class cls){
//cglib 增强类对象
Enhancer enhancer =new Enhancer();
// 设置增强类类型
enhancer.setSuperclass(cls);
// 定义代理逻辑为当前对象,要求当前对象实现methodInterceptor方法
enhancer.setCallback(this);
//生成并返回代理对象
return enhancer.create();
}
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
log.error("调度真实对象前");
Object result = methodProxy.invokeSuper(o,objects);
log.error("调度真实对象后");
return result;
}
}
使用cglib代理对象
写个需要被代理的对象定义一个sayHello方法
public class ReflectServiceImpl {
public void sayHello(String name){
System.err.println("hello"+name);}
使用cglib代理这个类,注意 这个类没有实现任何接口
public class CglibProxyTest {
public static void main(String[] args) {
CglibProxyExample cpe = new CglibProxyExample();
ReflectServiceImpl obj = (ReflectServiceImpl) cpe.getProxy(ReflectServiceImpl.class);
obj.sayHello("张三");
}
}
控制台输出
21:18:16.711 [main] ERROR com.example.reflectdemo.cglibproxy.CglibProxyExample - 调度真实对象前
hello张三
21:18:16.743 [main] ERROR com.example.reflectdemo.cglibproxy.CglibProxyExample - 调度真实对象后
——————————————————————————————————
我的理解是:
拦截器interceptor运用动态代理方法实现spring中aop的思想
1.定义一个拦截器接口 在其中添加三个方法,设计初期方法逻辑如下
**
* @author Liu Kai
* @Description: TODO 拦截器学习
*方法逻辑:
* proxy 代理对象
* target 真实对象
* method 方法
* args 运行方法的参数
*
* before方法返回boolean值,在真实对象前调用,
* 返回true,反射真实对象
* 返回false,调用around方法
*
* 调用真实对象方法或者around方法后,调用after方法
*
* @date 2018/9/10 17:33
*/
public interface Interceptor {
boolean before(Object proxy, Object target, Method method, Object[] args);
void around(Object proxy, Object target, Method method, Object[] args);
void after(Object proxy, Object target, Method method, Object[] args);
}
2.写个实现类
public class MyInterceptor implements Interceptor {
@Override
public boolean before(Object proxy, Object target, Method method, Object[] args) {
System.out.println("反射方法前逻辑");
return true;
}
@Override
public void around(Object proxy, Object target, Method method, Object[] args) {
System.out.println("取代了被代理对象的方法");
}
@Override
public void after(Object proxy, Object target, Method method, Object[] args) {
System.out.println("反射方法后逻辑");
}
}
3.在代理中使用拦截器
public class InterceptorJdkProxy implements InvocationHandler {
private Object target; // 真实对象
private String interceptorClass = null; //拦截器权限定名
public InterceptorJdkProxy(Object target, String interceptorClass) {
this.target = target;
this.interceptorClass = interceptorClass;
}
/**
* TODO 绑定委托对象并返回一个【代理占位】
*
* @param target 真实对象
* @return 代理对象【占位】
* @date 2018/9/10 18:03
* @author Liu Kai
**/
public static Object bind(Object target, String interceptorClass) {
return Proxy.newProxyInstance(target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
new InterceptorJdkProxy(target, interceptorClass));
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if(interceptorClass == null){
//没有设置拦截器则直接返回原有方法
return method.invoke(target,args);
}
Object result = null;
//通过反射生成拦截器
Interceptor interceptor = (Interceptor) Class.forName(interceptorClass).newInstance();
if(interceptor.before(proxy,target,method,args)){
//反射原有方法
result = method.invoke(target,args);
}else {
//返回false 执行around方法
interceptor.around(proxy,target,method,args);
}
//调用后置方法
interceptor.after(proxy,target,method,args);
return result;
}
}
测试
public class InterceptorTest {
public static void main(String[] args) {
HelloWorld proxy = (HelloWorld) InterceptorJdkProxy.bind(new HelloWorldImpl(),
"com.example.reflectdemo.interceptor.MyInterceptor");
proxy.sayHelloWorld();
}
}
结果
反射方法前逻辑
hello world
反射方法后逻辑
通过代理模式实现责任链或者aop的思想
可以定义多个interceptor
HelloWorld porxy1 = (HelloWorld) InterceptorJdkProxy.bind(new HelloWorldImpl()),"Interceptor1")
HelloWorld porxy2 = (HelloWorld) InterceptorJdkProxy.bind(proxy1,"Interceptor2")
HelloWorld porxy3 = (HelloWorld) InterceptorJdkProxy.bind(proxy2,"Interceptor3")
porxy3 .sayHelloWorld();
通过以上方法可以调用多个拦截器,形成责任链模式
明天计划的事情:(一定要写非常细致的内容)
学习数据结构
遇到的问题:(遇到什么困难,怎么解决的)
java设计除了偶观察者模式外 还有监听者模式
以及redis的订阅发布,
这些是否可以用到消息中心的设计中?
收获:(通过今天的学习,学到了什么知识)
了解了一些代理的知识
评论