装饰模式:以对客户端透明的方式扩展对象的功能,是继承关系的一个替代方案;

代理模式:给一个对象提供一个代理对象,并有代理对象来控制对原有对象的引用;

装饰模式为所装饰的对象增强功能;代理模式对代理的对象施加控制,并不提供对象本身的增强功能

简而言之,装饰者是指的是自身,对功能的增强,而另一种是调用接口,实现对代理对象的控制

在Spring AOP中,主要使用了两种代理方式:jdkProxy、cjlibProxy

cjlibProxy:

package com.cjlib;

import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy; import java.lang.reflect.Method; /**
* @author weining
* @date 2019/10/31 8:45
*/
public class CglibProxyExample implements MethodInterceptor { public Object getProxy(Class cls) {
//CGLIB enhancer 增强类对象
Enhancer enhancer = new Enhancer(); //设置增强类型
enhancer.setSuperclass(cls); //定义逻辑对象,要求实现当前对象实现MethodInterceptor方法
enhancer.setCallback(this); //返回代理对象
return enhancer.create();
} /**
* 代理逻辑方法
*
* @param o 代理对象
* @param method 方法
* @param objects 方法参数
* @param methodProxy 方法代理
* @return 代理逻辑返回
* @throws Throwable
*/
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("调用真是对象之前");
Object invokeSuper = methodProxy.invokeSuper(o, objects);
System.out.println("调用真是对象之后"); return invokeSuper;
}
}

  测试方法:

package com.cjlib;

import com.jdk.HelloWorld;
import com.jdk.impl.HelloWorldImpl; /**
* @author weining
* @date 2019/10/31 9:03
*/
public class testCGLIBProxy {
public static void main(String[] args) {
CglibProxyExample cglibProxyExample = new CglibProxyExample();
HelloWorld helloWorld = (HelloWorldImpl) cglibProxyExample.getProxy(HelloWorldImpl.class);
helloWorld.sayHello();
}
}

  

jdkProxy:

package com.jdk;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy; /**
* @author weining
* @date 2019/10/31 8:29
* 在jdk动态代理时 必须要实现InvocationHandler接口
* 自动生成接口中的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);
} /**
* invoke可以实现代理对象
* @param proxy bind 返回的对象
* @param method 当前调度的方法
* @param args 调度方法的参数
* @return 代理的结果返回
* @throws Throwable
*/
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;
}
}

这时,创建一个HelloWorld接口:

package com.jdk;

/**
* @author weining
* @date 2019/10/31 8:27
*/
public interface HelloWorld {
public void sayHello();
}

创建接口的实现类:

package com.jdk.impl;

import com.jdk.HelloWorld;

/**
* @author weining
* @date 2019/10/31 8:27
*/
public class HelloWorldImpl implements HelloWorld {
public void sayHello() {
System.out.println("Hello,World!");
}
}

最后调用测试方法:

package com.jdk;

import com.jdk.impl.HelloWorldImpl;

/**
* @author weining
* @date 2019/10/31 8:40
*/
public class test {
public static void main(String[] args) {
JdkProxyExample jdkProxyExample = new JdkProxyExample(); HelloWorld proxy = (HelloWorld) jdkProxyExample.bind(new HelloWorldImpl());
proxy.sayHello(); }
}

两者的区别

1)JDK动态代理只能对实现了接口的类生成代理,而不能针对类。

2)CGLIB是针对类实现代理,主要是对指定的类生成一个子类,覆盖其中的方法,

并覆盖其中方法实现增强,但是因为采用的是继承,所以该类或方法最好不要声明成final,

对于final类或方法,是无法继承的。

装饰者模式:

//装饰器模式
public class Decorator implements Component{
private Component component;
public Decorator(Component component){
this.component = component
}
public void operation(){
….
component.operation();
….
}
}
//装饰器的客户
public class Client{
public static void main(String[] args){
//客户指定了装饰者需要装饰的是哪一个类
Component component = new Decorator(new ConcreteComponent());

}
}

最新文章

  1. 大气漂亮的jQuery水晶样式下拉菜单
  2. 初学python里的yield send next
  3. 反射和动态代理实现上下文切入AOP效果
  4. SSH原理与运用
  5. Codeforces Round #229 (Div. 2) C
  6. LR工具使用之结果分析
  7. C语言实现二叉树-利用二叉树统计单词数目
  8. multiparty
  9. Java Synchronized Blocks vs. Methods
  10. QTP的基本功能介绍
  11. sql server、c# 命名规范
  12. c#和java中的方法覆盖——virtual、override、new
  13. BZOJ3237: [Ahoi2013]连通图
  14. spring使用redis做缓存
  15. jenkins-参数化构建(一)
  16. 设计模式学习心得<代理模式 Proxy>
  17. CSS3 Flexbox轻巧实现元素的水平居中和垂直居中
  18. JavaScript基础知识(数据类型)
  19. Akka-Cluster(1)- Cluster Singleton 单例节点
  20. Sereja ans Anagrams 优先队列控制

热门文章

  1. SpringCloud之异常报警通知(八)
  2. C++学习笔记4_new和delete
  3. [考试反思]0815NOIP模拟测试22
  4. noip11 string
  5. NOIP模拟 22
  6. 聚类——密度聚类DBSCAN
  7. Linux 常用命令 | top 详解
  8. 连接xshell 时 连不上的问题
  9. golang 服务诡异499、504网络故障排查
  10. 还看不懂同事的代码?超强的 Stream 流操作姿势还不学习一下