前文讲了, 可以利用Spring, Guice等框架提供的容器实现AOP, 如果想绕过容器, 直接注入Class,

可以利用Cglib为对象加上动态代理,实现代码切入, 但是每次调用比较繁琐,

因此我们还需要给他加了一层语法糖, 使之更易用.

Advice

Spring带了一堆Advice, 我们只模拟实现环绕Advice, 以及增加了一个Clear切入的注解, 下面看具体实现.

 /**
* 环绕Advie
*
* 可以加在类上, 或者方法上.
* 加在类上的话, 类中所有无@Clear注解的方法都会被切入
*
* @Before({CustomInterceptor.class, B.class})
* @Before(CustomInterceptor.class)
*/
@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD})
public @interface Before {
Class<? extends Interceptor>[] value();
}
 /**
* 清除Advice
*
* 可以清除方法上的指定Interceptor, 若不指定, 则清除所有切入.
*
* @Clear 清除所有
* @Clear(CustomInterceptor.class) 清除CustomInterceptor
*/
@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD})
public @interface Clear {
Class<? extends Interceptor>[] value() default {};
}

语法糖

直接调用Cglib做切入, 需要setSuperClass, setCallback等等.

   Enhancer enhancer = new Enhancer();
  enhancer.setSuperclass(AopDemo.class);
  enhancer.setCallback(new MethodInterceptorImpl());   AopDemo demo = (AopDemo) enhancer.create();

我们需要对Enhancer以及Callback进行封装, 减少复杂度

 import java.util.concurrent.ConcurrentHashMap;

 /**
* cglib中Enhancer的语法糖, 让注入更简单点
*/
public class Enhancer { private static final ConcurrentHashMap<String, Object> singleton = new ConcurrentHashMap<String, Object>(); private Enhancer(){} public static <T> T enhance(Class<T> targetClass) {
return (T)net.sf.cglib.proxy.Enhancer.create(targetClass, new Callback());
} public static <T> T enhance(Class<T> targetClass, Interceptor... injectInters) {
return (T)net.sf.cglib.proxy.Enhancer.create(targetClass, new Callback(injectInters));
} public static <T> T getTarget(String singletonKey) {
return (T)singleton.get(singletonKey);
} public static <T> T enhance(String singletonKey, Class<T> targetClass) {
Object target = singleton.get(singletonKey);
if (target == null) {
target = enhance(targetClass);
singleton.put(singletonKey, target);
}
return (T)target;
} public static <T> T enhance(String singletonKey, Class<T> targetClass, Interceptor... injectInters) {
Object target = singleton.get(singletonKey);
if (target == null) {
target = enhance(targetClass, injectInters);
singleton.put(singletonKey, target);
}
return (T)target;
}
public static <T> T enhance(Object target) {
return (T)net.sf.cglib.proxy.Enhancer.create(target.getClass(), new Callback(target));
} public static <T> T enhance(Object target, Interceptor... injectInters) {
return (T)net.sf.cglib.proxy.Enhancer.create(target.getClass(), new Callback(target, injectInters));
}
public static <T> T enhance(String singletonKey, Object target) {
Object result = singleton.get(singletonKey);
if (result == null) {
result = enhance(target);
singleton.put(singletonKey, result);
}
return (T)result;
} public static <T> T enhance(String singletonKey, Object target, Interceptor... injectInters) {
Object result = singleton.get(singletonKey);
if (result == null) {
result = enhance(target, injectInters);
singleton.put(singletonKey, result);
}
return (T)result;
} } import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy; import java.lang.reflect.Method;
import java.util.HashSet;
import java.util.Set; /**
* Callback.
*/
class Callback implements MethodInterceptor { private Object injectTarget = null;
private final Interceptor[] injectInters; private static final Set<String> excludedMethodName = buildExcludedMethodName();
private static final InterceptorManager interMan = InterceptorManager.me(); public Callback() {
this.injectInters = InterceptorManager.NULL_INTERS;
} public Callback(Interceptor... injectInters) {
checkInjectInterceptors(injectInters);
this.injectInters = injectInters;
} public Callback(Object injectTarget, Interceptor... injectInters) {
if (injectTarget == null) {
throw new IllegalArgumentException("injectTarget can not be null.");
}
checkInjectInterceptors(injectInters);
this.injectTarget = injectTarget;
this.injectInters = injectInters;
} private void checkInjectInterceptors(Interceptor... injectInters) {
if (injectInters == null) {
throw new IllegalArgumentException("injectInters can not be null.");
}
for (Interceptor inter : injectInters) {
if (inter == null) {
throw new IllegalArgumentException("interceptor in injectInters can not be null.");
}
}
} public Object intercept(Object target, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
if (excludedMethodName.contains(method.getName())) {
// if (method.getName().equals("finalize"))
// return methodProxy.invokeSuper(target, args);
// return this.injectTarget != null ? methodProxy.invoke(this.injectTarget, args) : methodProxy.invokeSuper(target, args); // 保留上面注释部分,此处为优化
if (this.injectTarget == null || method.getName().equals("finalize")) {
return methodProxy.invokeSuper(target, args);
} else {
return methodProxy.invoke(this.injectTarget, args);
}
} if (this.injectTarget != null) {
target = this.injectTarget;
Interceptor[] finalInters = interMan.buildServiceMethodInterceptor(injectInters, target.getClass(), method);
Invocation invocation = new Invocation(target, method, args, methodProxy, finalInters);
invocation.useInjectTarget = true;
invocation.invoke();
return invocation.getReturnValue();
}
else {
Class<?> targetClass = target.getClass();
if (targetClass.getName().indexOf("$$EnhancerByCGLIB") != -1) {
targetClass = targetClass.getSuperclass();
}
Interceptor[] finalInters = interMan.buildServiceMethodInterceptor(injectInters, targetClass, method);
Invocation invocation = new Invocation(target, method, args, methodProxy, finalInters);
invocation.useInjectTarget = false;
invocation.invoke();
return invocation.getReturnValue();
}
} private static final Set<String> buildExcludedMethodName() {
Set<String> excludedMethodName = new HashSet<String>();
Method[] methods = Object.class.getDeclaredMethods();
for (Method m : methods) {
excludedMethodName.add(m.getName());
}
// getClass() registerNatives() can not be enhanced
// excludedMethodName.remove("getClass");
// excludedMethodName.remove("registerNatives");
return excludedMethodName;
}
}

封装后可以直接使用一句话, 还可用来增强已有对象

         AopDemo demo = Enhancer.enhance(AopDemo.class);

示例

 @Before({PrivilegeInterceptor.class, LogInterceptor.class})
public class AopDemo { public static void main(String[] args){
AopDemo demo = Enhancer.enhance(AopDemo.class);
demo.doSomething();
demo.doOtherthing(); } public void doOtherthing() {
// 默认沿用Class的interceptor
System.out.println("do 111111111111111");
} @Clear(PrivilegeInterceptor.class)
public void doSomething() {
// 手动清除了权限Interceptor
System.out.println("do 222222222222222");
}
}
 public class LogInterceptor implements Interceptor{
@Override
public void intercept(Invocation inv) {
inv.invoke();
System.out.println("Log记录入库");
}
} public class PrivilegeInterceptor implements Interceptor{
@Override
public void intercept(Invocation inv) {
System.out.println("鉴权成功");
inv.invoke();
}
}
doOtherthing执行结果

鉴权成功
do 111111111111111
Log记录入库

doSomething执行结果

do 222222222222222
Log记录入库

其他使用

直接用来增强对象
         AopDemo demoSinle1 = Enhancer.enhance(AopDemo.getInstance());
在enhance里new Interceptor
         AopDemo demo3 = Enhancer.enhance(AopDemo.class, new Interceptor() {
@Override
public void intercept(Invocation inv) {
System.out.println("new before");
inv.invoke();
System.out.println("new after");
}
});
demo3.doSomething();
在需要增强的方法上写@Before
     @Before(LogInterceptor.class)
public void doOtherthing() {
}
 

利用Cglib实现AOP的更多相关文章

  1. (转)使用CGLIB实现AOP功能与AOP概念解释

    http://blog.csdn.net/yerenyuan_pku/article/details/52864395 使用CGLIB实现AOP功能 在Java里面,我们要产生某个对象的代理对象,这个 ...

  2. 利用cglib生成动态java bean

    cglib详细学习 http://blog.csdn.net/u010150082/article/details/10901641 cglib-nodep jar报下载 http://grepcod ...

  3. 利用C#实现AOP常见的几种方法详解

    利用C#实现AOP常见的几种方法详解 AOP面向切面编程(Aspect Oriented Programming) 是通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术. 下面这篇文章主要 ...

  4. Spring进阶之路(10)-Advice简单介绍以及通过cglib生成AOP代理对象

    Advice简单介绍 1. Before:在目标方法运行之前运行织入.假设Before的处理中没有进行特殊的处理.那么目标方法终于会运行,可是假设想要阻止目标方法运行时.能够通过抛出一个异常来实现.B ...

  5. 利用CGLib实现动态代理实现Spring的AOP

    当我们用Proxy 实现Spring的AOP的时候, 我们的代理类必须实现了委托类的接口才能实现. 而如果代理类没有实现委托类的接口怎么办? 那么我们就可以通过CGLib来实现 package cn. ...

  6. 利用cglib包实现Spring中aop的<aop:advisor>功能

    一:前言 还有<aop:before>/<aop:after>/<aop:around>的没有实现,不过根<aop:advisor>是差不多的,就是要额 ...

  7. ssm+redis 如何更简洁的利用自定义注解+AOP实现redis缓存

    基于 ssm + maven + redis 使用自定义注解 利用aop基于AspectJ方式 实现redis缓存 如何能更简洁的利用aop实现redis缓存,话不多说,上demo 需求: 数据查询时 ...

  8. JAVA动态代理和方法拦截(使用CGLib实现AOP、方法拦截、委托)

    AOP用CGLib更简便.更可控. 动态代理的实现非常优雅. 实体类: public class SampleClass { public String MyFunction1(String inpu ...

  9. Java入门到精通——调错篇之Spring2.5利用aspect实现AOP时报错: error at ::0 can't find referenced pointcut XXX

    一.问题描述及原因. 利用Aspect注解实现AOP的时候出现了error at ::0 can't find referenced pointcut XXX.一看我以为注解写错了,结果通过查询相关资 ...

随机推荐

  1. ubuntu:通过封装验证码类库一步步安装php的gd扩展

    我相信很多人的lamp环境都是直接复制一堆参数安装进去的,这里有可能成功,也有可能失败,如果是新手,估计要碰到各种错误,就算安装成功,也未必知道那些参数是干嘛的,反正装进去能用就行. 我当初开始的时候 ...

  2. display 的 32 种写法

    从大的分类来讲, display的 32种写法可以分为 6个大类,再加上 1个全局类,一共是 7大类: 外部值 内部值 列表值 属性值 显示值 混合值 全局值 外部值 所谓外部值,就是说这些值只会直接 ...

  3. Js比较对Object类型进行排序

    <script> var data=[{name:"121",age:"18",year:"2018"},{name:" ...

  4. axios + mock.js模拟数据实现前后端分离开发的实例代码

    首先就是必须安装axios和mock.js npm install axios npm install mockjs 1. 然后在文档src中新建一个mock.js文件,如图 2. 在main.js中 ...

  5. EmguCV创建/保存图片

    Image图片类 public Image(Bitmap bmp);//采用 Bitmap 图像创建. public Image(string fileName);//指定路径创建图像. public ...

  6. ubuntu14.04 安装redis 2.8.9

    ubuntu14.04安装前准备工作,为了保证安装顺利,请先执行apt-get update 然后安装make 和gcc(已安装的可忽略) apt-get install make apt-get i ...

  7. 项目使用EntityFramework需要做的几项工作

    1..新项目引用创建好的其他项目,比如实体类库.数据库业务.实体数据模型等需要用到的项目进行引用. 2.新项目使用NuGet获取AutoMapper和EntityFramework程序包进行安装引用, ...

  8. 基于全志H3芯片的ARM开发环境搭建

    基于全志H3芯片的ARM开发环境搭建 最近买了个友善之臂的NanoPi M1板子,又在网上申请了个NanoPi NEO板子,这两个都是基于全志H3芯片的Crotex-A7四核ARM开发板,两个板子可以 ...

  9. FusionCharts 2D柱状图和折线图的组合图

    1.设计思路 (1)了解组合图的特性以及用法,选用图的类型: (2)设计出两根柱子和两根折线,分开展示. 2.设计步骤 (1)设计页面 Column2DLine.html: <!DOCTYPE ...

  10. Nginx负载均衡和反向代理的配置和优化

    负载均衡 负载均衡是由多台服务器以对称的方式组成一个服务器集合,每台服务器都具有等价的地位, 反向代理 是指以代理服务器来接受internet上的请求,然后将请求转给内部的服务器 常见的负载均衡 1. ...