asp网站怎么验证到百度站长,cad做兼职区哪个网站,招投标网站销售怎么做,公司门口设计什么是代理模式为其他对象提供一种代理以控制对这个对象的访问。为什么使用代理模式中介隔离#xff1a;在某些情况下#xff0c;一个客户类不想或者不能直接引用一个委托对象#xff0c;而代理类对象可以在客户类和委托对象之间起到中介的作用#xff0c;其特征是代理类和…什么是代理模式为其他对象提供一种代理以控制对这个对象的访问。为什么使用代理模式中介隔离在某些情况下一个客户类不想或者不能直接引用一个委托对象而代理类对象可以在客户类和委托对象之间起到中介的作用其特征是代理类和委托类实现相同的接口。开闭原则增加功能代理类除了是客户类和委托类的中介之外我们还可以通过给代理类增加额外的功能来扩展委托类的功能这样做我们只需要修改代理类而不需要再修改委托类符合代码设计的开闭原则。代理类主要负责为委托类预处理消息、过滤消息、把消息转发给委托类以及事后对返回结果的处理等。代理类本身并不真正实现服务而是同过调用委托类的相关方法来提供特定的服务。真正的业务功能还是由委托类来实现但是可以在业务功能执行的前后加入一些公共的服务。例如我们想给项目加入缓存、日志这些功能我们就可以使用代理类来完成而没必要打开已经封装好的委托类。代理模式实现原理代理模式主要包含三个角色即抽象主题角色(Subject)、委托类角色(被代理角色Proxied)以及代理类角色(Proxy)抽象主题角色Subject可以是接口也可以是抽象类委托类角色proxied真实主题角色业务逻辑的具体执行者代理类角色Proxy内部含有对真实对象RealSubject的引用负责对真实主题角色的调用并在真实主题角色处理前后做预处理和后处理代理模式应用场景SpringAop、日志收集、权限控制、过滤器、RPC远程调用代理模式创建的方式静态代理 和 动态代理静态代理静态代理是由程序员创建或工具生成代理类的源码再编译代理类。所谓静态也就是在程序运行前就已经存在代理类的字节码文件代理类和委托类的关系在运行前就确定了。一句话自己手写代理类就是静态代理。基于接口实现方式//主题Subject
public interface OrderService {void order();
}
//实现接口
public class OrderServiceImpl implements OrderService {public void order() {System.out.println(用户下单操作..);}
}
//代理类
public class OrderServiceProxy implements OrderService {/*** 代理对象*/private OrderService proxiedOrderService;public OrderServiceProxy( OrderService orderService) {this.proxiedOrderServiceorderService;}public void order() {System.out.println(日志收集开始..);proxiedOrderService.order();System.out.println(日志收集结束..);}
}
//测试
public class ClientTest {public static void main(String[] args) {OrderService orderService new OrderServiceProxy(new OrderServiceImpl());orderService.order();}
}
接口继承方式实现//继承接口实现类
public class OrderServiceProxy extends OrderServiceImpl {public void order() {System.out.println(日志收集开始..);super.order();System.out.println(日志收集结束..);}
}
//测试
public class ClientTest {public static void main(String[] args) {OrderService orderService new OrderServiceProxy();orderService.order();}
}动态代理动态代理是在实现阶段不用关心代理类而在运行阶段才指定哪一个对象。动态代理类的源码是在程序运行期间由JVM根据反射等机制动态的生成 。JDK动态代理JDK动态代理的一般步骤如下1.创建被代理的接口和类2.实现InvocationHandler接口对目标接口中声明的所有方法进行统一处理3.调用Proxy的静态方法创建代理类并生成相应的代理对象//主题Subject
public interface OrderService {void order();
}
//实现接口
public class OrderServiceImpl implements OrderService {public void order() {System.out.println(修改数据库订单操作..);}
}
//代理类
public class JdkInvocationHandler implements InvocationHandler {/*** 目标代理对象*/public Object target;public JdkInvocationHandler(Object target) {this.target target;}public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println(日志收集开始);// 执行代理对象方法Object reuslt method.invoke(target, args);System.out.println(日志收集结束);return reuslt;}/*** 获取代理对象接口** param T* return*/public T T getProxy() {return (T) Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);}}
JdkInvocationHandler jdkInvocationHandler new JdkInvocationHandler(new OrderServiceImpl());
OrderService proxy jdkInvocationHandler.getProxy();
proxy.order();原理分析1.获取代理的生成的class文件 System.getProperties().put(sun.misc.ProxyGenerator.saveGeneratedFiles, true);
2.使用反编译工具该Proxy0.class注意继承了Proxy类实现了代理的接口由于java不能多继承这里已经继承了Proxy类了不能再继承其他的类所以JDK的动态代理不支持对实现类的代理只支持接口的代理。CGLIB动态代理Cglib是一个强大的高性能高质量的代码生成类库。它可以在运行期扩展JAVA类与实现JAVA接口。其底层实现是通过ASM字节码处理框架来转换字节码并生成新的类。大部分功能实际上是ASM所提供的Cglib只是封装了ASM简化了ASM操作实现了运行期生成新的class。CGLIB原理运行时动态的生成一个被代理类的子类通过ASM字节码处理框架实现子类重写了被代理类中所有非final的方法。在子类中采用方法拦截的技术拦截所有父类方法的调用顺势植入横切逻辑。Cglib优缺点优点JDK动态代理要求被代理的类必须实现接口当需要代理的类没有实现接口时Cglib代理是一个很好的选择。另一个优点是Cglib动态代理比使用java反射的JDK动态代理要快缺点对于被代理类中的final方法无法进行代理因为子类中无法重写final函数CGLIB代理实现实现MethodInterceptor接口的intercept方法后所有生成的代理方法都调用这个方法。intercept方法的具体参数有obj 目标类的实例1.method 目标方法实例通过反射获取的目标方法实例 2.args 目标方法的参数 3.proxy 代理类的实例该方法的返回值就是目标方法的返回值。public class OrderServiceImpl {public void order() {System.out.println(用户下单操作..);}
}
public class CglibMethodInterceptor implements MethodInterceptor {public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {System.out.println(日志收集开始...);Object reuslt proxy.invokeSuper(obj, args);System.out.println(日志收集结束...);return reuslt;}
}System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, D:code);
CglibMethodInterceptor cglibMethodInterceptor new CglibMethodInterceptor();
Enhancer enhancer new Enhancer();
// 设置代理类的付类
enhancer.setSuperclass(OrderServiceImpl.class);
// 设置回调对象
enhancer.setCallback(cglibMethodInterceptor);
// 创建代理对象
OrderServiceImpl orderServiceImpl (OrderServiceImpl) enhancer.create();
orderServiceImpl.order();Maven依赖dependenciesdependencygroupIdcglib/groupIdartifactIdcglib/artifactIdversion3.2.12/version/dependency
/dependencies结果cglib日志收集开始....执行订单业务逻辑代码cglib日志收集结束....静态代理与动态代理区别静态代理需要自己写代理类而动态代理不需要写代理类。JDK动态代理与CGLIB实现区别JDK动态代理底层实现:JDK的动态代理使用Java的反射技术生成动态代理类只能代理实现了接口的类 没有实现接口的类不能实现动态代理。CGLIB动态代理底层实现:运行时动态的生成一个被代理类的子类通过ASM字节码处理框架实现子类重写了被代理类中所有非final的方法在子类中采用方法拦截的技术拦截所有父类方法的调用不需要被代理类对象实现接口从而CGLIB动态代理效率比Jdk动态代理反射技术效率要高。案例使用AOP拦截Controller所有请求日志Aspect
Component
Slf4j
public class AopLogAspect {// 申明一个切点 里面是 execution表达式Pointcut(execution(* com.xuyu.controller.*.*(..)))private void serviceAspect() {}// 请求method前打印内容Before(value serviceAspect())public void methodBefore(JoinPoint joinPoint) {ServletRequestAttributes requestAttributes (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();HttpServletRequest request requestAttributes.getRequest();// 打印请求内容log.info(请求内容);log.info(请求地址: request.getRequestURL().toString());log.info(请求方式: request.getMethod());log.info(请求类方法: joinPoint.getSignature());log.info(请求类方法参数: Arrays.toString(joinPoint.getArgs()));log.info(请求内容);}// 在方法执行完结后打印返回内容AfterReturning(returning o, pointcut serviceAspect())public void methodAfterReturing(Object o) {log.info(--------------返回内容----------------);log.info(Response内容: o.toString());log.info(--------------返回内容----------------);}
}Maven依赖信息parentgroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-parent/artifactIdversion2.0.1.RELEASE/version
/parent
dependenciesdependencygroupIdcglib/groupIdartifactIdcglib/artifactIdversion3.2.12/version/dependency!-- sprinboot web --dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-web/artifactId/dependencydependencygroupIdorg.projectlombok/groupIdartifactIdlombok/artifactIdversion1.16.10/version/dependencydependencygroupIdcommons-lang/groupIdartifactIdcommons-lang/artifactIdversion2.6/version/dependencydependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-aop/artifactId/dependency
/dependencies结果请求内容 : 请求地址:http://127.0.0.1:8080/getUser : 请求方式:GET : 请求类方法:String com.xuyu.service.controller.IndexController.getUser(String,Integer) : 请求类方法参数:[xuyu, 2] : 请求内容 : userName:{},xuyu : --------------返回内容---------------- : Response内容:success_getUser : --------------返回内容----------------作者须臾之余来源开源中国原文https://my.oschina.net/u/3995125/blog/3051269 福利专区动态代理及应用深度解析|Java SE视频课程 - 蛙课视频www.wkcto.com