静态代理: 为什么要代理?在不改动原代码的基础上,丰富调用某个方法时实现的功能。 比如service类中原本update只会更新,但是通过代理类加上了判断权限和输出时间的功能。 其实这些功能也可以写在原代码的类里,那为什么不这样写,而要多此一举的写在代理类里呢? 因为这些功能是根据实际情况经常需要变动的!!!写在代理类里,解耦,方便更改! 静态代理模式在不改变目标对象的前提下,实现了对目标对象的功能扩展。 不足:静态代理实现了目标对象的所有方法,一旦目标接口增加方法,代理对象和目标对象都要进行相应的修改,增加维护成本。
==============================================================
动态代理:
根据上述静态代理的不足,怎么解决?我们自己也可以解决,无非是根据根据想要代理的类,通过反射获得他所有的方法名,然后在方法被调用前后分别插入一些 *** 作,这就叫做动态代理!java官方给我提供了实现上述 *** 作的一个接口,叫做的InvocationHandler接口,其实这个接口也就是通过反射获取需要代理类的方法Method,然后在method.invoke(target)调用前、调用后加上我们自定义的 *** 作。
不足:
- JDK的动态代理有一个限制,就是使用动态代理的对象必须实现一个或多个接口。
如果想代理没有实现接口的类,就可以使用CGLIB实现。
package com.ldj.proxy.demo.动态代理; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; //想实现动态代理,只需要实现Java提供的InvocationHandler接口,其实这个接口也就是通过反射获取需要代理类的方法名,然后在这些方法被调用前加上我们自定义的 *** 作 public class AdminServiceInvocation implements InvocationHandler { private Object target; public AdminServiceInvocation(Object target) { this.target = target; } public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("在这书写被代理的对象方法被执行之前需要做的 *** 作。判断用户是否有权限进行 *** 作"); Object obj = method.invoke(target);//通过反射执行被代理对象原本的方法 System.out.println("在这书写被代理的对象方法被执行之后需要做的 *** 作。记录用户执行 *** 作的用户信息、更改内容和时间等"); return obj; } }
回顾下java的反射:
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; public class e_反射获取成员方法并调用 { //Method[] getMethods()返回所有公共成员方法对象的数组,包括继承的 //Method[] getDeclaredMethods()返回所有成员方法对象的数组,不包括继承的 //Method getMethod(String name, Class>...parameterTypes)返回单个公共成员方法对象 //Method getDeclaredMethod(String name, Class>...parameterTypes)返回单个成员方法对象 public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException { System.out.println("/================================================"); Class clazz = Class.forName("Student"); Method study = clazz.getMethod("study");//获取public空参成员方法 System.out.println(study); System.out.println("/================================================"); Method study1 = clazz.getMethod("study", String.class);//获取public带参成员方法 System.out.println(study1); System.out.println("/================================================"); Method hide = clazz.getDeclaredMethod("hide");//获取private私有空参成员方法 System.out.println(hide); //获取成员方法并调用 System.out.println("/================================================"); Method study2 = clazz.getMethod("study2", String.class); Object res = study2.invoke(clazz.getConstructor().newInstance(), "aaaaa"); System.out.println(res); } }
======================================================
cglib代理:
cglib参考文章https://segmentfault.com/a/1190000011291179https://segmentfault.com/a/1190000011291179
其实实现都是一样的,通过代理类在原方法执行前后增加一些 *** 作:
========================================================================
如上,了解三种实现代理的方式,那么spring AOP功能如何实现?spring的AOP默认采用的就是如上述的动态代理!当需要代理的类不是代理接口的时候,Spring会切换为使用CGLIB代理,也可通过设置强制使用CGLIB,而且spring-aspect包内部默认自带cglib的依赖。
spring通过XML实现AOP是怎么实现的呢?参考下文
Spring系列(四):Spring AOP详解和实现方式(xml配置和注解配置) - 小不点啊 - 博客园参考文章:http://www.cnblogs.com/hongwz/p/5764917.html 一、什么是AOP AOP(Aspect Oriented Programming),即面向切面编程,https://www.cnblogs.com/leeSmall/p/7667040.html 完成的项目结构如下:
·接下来用纯注解实现AOP
通知:加什么?
切入点:加在哪?
接入点:能够加在哪?
配置类上书写@EnableAspectJAutoProxy
AOP切入点表达式:标准格式,接口的方法、实现类的方法、通配符
AOP通知类型5种:......
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)