郑州网站提升排名,专业外贸网站制作公司,wordpress重装主题,外贸营销员职业技能证书说起Spring的AOP(Aspect-Oriented Programming)面向切面编程大家都很熟悉#xff08;Spring不是这次博文的重点#xff09;#xff0c;但是我先提出几个问题#xff0c;看看同学们是否了解#xff0c;如果了解的话可以不用继续往下读#xff1a; 1. Spring的AOP的实现方式… 说起Spring的AOP(Aspect-Oriented Programming)面向切面编程大家都很熟悉Spring不是这次博文的重点但是我先提出几个问题看看同学们是否了解如果了解的话可以不用继续往下读 1. Spring的AOP的实现方式有哪些 2. 为什么使用代理机制 3. 它们是怎么实现的 4. 它们的区别是什么 下面进入正题Spring采用代理的方式实现AOP具体采用了JDK的动态代理和CGLib实现。使用动态代理和CGLib的目的是在现有类的基础上增加一些功能。简单地将就是有一个Proxy类实现了原始类的方法并且在原始类的基础上增加了新的功能。那么这么做可以实现很多功能 1. 在方法前后进行日志处理。 2. 进行额外的校验比如参数的验证功能等。 3. 实现一些懒加载也就是实例化的时候如果不去调用真正的方法的时候这个类的属性就不会存在Hibernate有这样类似的功能。 下面咱们用简单的代码实现它是如何进行代理的首先采用的是JDK的动态代理实现 定义一个接口 package com.hqs.proxy;/*** 操作系统光接口* author hqs**/
public interface OpSystem {public void work();
} 定义一个实现类 package com.hqs.proxy;/*** Mac 的实现* author hqs**/
public class Mac implements OpSystem {public void work() {System.out.println(Mac is running); }} 关键位置来了我们通过实现JDK自带的反射机制的包的InvocationHandler来进行反射处理实现它之后需要实现里边的invoke方法这个invoke方法里边的参数分别为代理类实例用于调用method的method参数是实际执行的方法args所传输的参数数组。 package com.hqs.proxy;import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;public class OpHandler implements InvocationHandler {private final OpSystem ops; public OpHandler(OpSystem ops) {this.ops ops;}public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println(Before system running);method.invoke(ops, args);System.out.println(After system running);return null;}public static void main(String[] args) {Mac mac new Mac();OpHandler oph new OpHandler(mac);OpSystem os (OpSystem)Proxy.newProxyInstance(oph.getClass().getClassLoader(),mac.getClass().getInterfaces(), oph);os.work();System.out.println(os.getClass());}}输出
Before system running
Mac is running
After system running
class com.sun.proxy.$Proxy0 然后看到里边的main方法中代理类实例化对象的方法Proxy.newProxyInstance这个是JDK的反射方法去实例化代理类其中有三个参数分别是去实例化代理类的class loader所代理的类的所有接口Class数组hander处理类用于做拦截使用的类。最后我输出了一下os.getClass()大家可以看到的是代理类的实例而不是真正代理类的实例这么做的好处就是很方便的复用这个代理类比如你可以重复调用它而不用去重新实例化新类再一点就是你可以针对不同的方法进行拦截比如你可以method.getName()去判断调用的方法名字是什么从而更细粒度的拦截方法。咱们继续看用CGLib的实现 package com.hqs.proxy;import java.lang.reflect.Method;import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;/*** CGLib Interceptor用于方法拦截* author hqs**/
public class CGLibInterceptor implements MethodInterceptor {private final Mac mac;public CGLibInterceptor(Mac mac) {this.mac mac;}Overridepublic Object intercept(Object obj, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {System.out.println(Before system running);method.invoke(mac, args);System.out.println(After system running);return null;}public static void main(String[] args) {Mac mac new Mac(); //实例而非接口MethodInterceptor handler new CGLibInterceptor(mac);Mac m (Mac)Enhancer.create(mac.getClass(), handler);m.work();System.out.println(m.getClass());}}输出
Before system running
Mac is running
After system running
class com.hqs.proxy.Mac$$EnhancerByCGLIB$$1f2c9d4a 首先需要引入cglib包然后才能使用他的MethodInterptor,它也采用method.invoke实现对代理类的调用。它的代理类创建采用Enhancer的create方法其中传入了需要创建的类的class以及Callback对象因为MethodInterceptor继承了Callback对象。用于指向方法前后进行调用的类。 public interface MethodInterceptor
extends Callback 这是这两个类的基本实现那么它们的区别是什么呢 JDK的动态代理只能针对接口和其实现类如果没有实现类只有接口也是可以代理的这里就不在举例了。为什么JDK的动态代理只针对接口代理因为这个是JDK的定义。如果不针对接口实现动态代理那就用到了CGLib了也就是可以针对具体的类进行代理大家可以参考我的代码。 这些是它们的根本区别但是Spring推荐使用JDK的动态代理面向接口去编程。使用CGLib去做代理的时候需要注意它生成的代理类存放在JVM的Perm space里边那么是不是生成的代理对象就不进行回收了其实不是的不经常回收但是还是回收的当类被加载加载类的classLoader什么时候变得对垃圾回收可用的时候才进行回收。也就是你自己创建所有类移除classLoader之后那么这个classLoader就会被回收一般非常精通CGLib的话可以进行这块内容深入开发因为它可以做出amzing的事情如果你熟悉的话。 如果有不对的地方欢迎拍砖~ 转载于:https://www.cnblogs.com/huangqingshi/p/7651376.html