前文讲了, 可以利用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. 利用while语句,条件为输入的字符不为'\n'.

    题目:输入一行字符,分别统计出其中英文字母.空格.数字和其它字符的个数. 1.程序分析:利用while语句,条件为输入的字符不为'\n'. 一个很简单的问题,其实换种方式就能完成,但是我就想怎么着才能 ...

  2. JavaScript 历史漫谈

    话说 JavaScript 其实是诞生在一个特殊的时期,20世纪90年代,正值第三次科技革命时期,互联网刚开始进入人们的生活.设想一下,在网速只有几十比特的那个时代,在登录注册时要花上很长一段时间等待 ...

  3. java中public private protected default的区别

    1.public:public表明该数据成员.成员函数是对所有用户开放的,所有用户都可以直接进行调用 2.private:private表示私有,私有的意思就是除了class自己之外,任何人都不可以直 ...

  4. MIPS中有关于分支指令及跳转寻址

    分支指令 分支指令包含该指令,和两个操作数,以及跳转的分支地址,该地址是相对于下一条指令的相对地址 分支指令占6位   操作数1占5位     操作数2占5位     分支指令16位 例如 bne  ...

  5. ElasticSearch 5.0.0 集群安装部署文档

    1.  搭建环境 3台物理机 操作系统 centos7 es1   192.168.31.141   4g内存   2核 es2   192.168.31.142   4g内存   2核 es3    ...

  6. EmguCV中图像类型进行转换

    1.       Bitmap:类型不在 Emgucv命名空间中 2.       Image<TColor, TDepth> 3.       Mat: 4.       UMat: 高 ...

  7. session不会过期

    $(function () { window.setInterval(function () { $.post('random.html'); }, 60000); }); 加在母版页里,使用与长时间 ...

  8. MacOS App代码申请管理员权限

    原文: https://jacobpan3g.github.io/cn/2018/02/07/gain-root-permission-for-mac-app/,有问题欢迎在原文评论区一起讨论交流,我 ...

  9. python调试

    如果很简单的程序,建议还是pirnt打出来. 对于Linux环境,使用pdb/ipdb是一个不错的选择. 安装ipdb sudo pip install ipdb 开启调试 手动在需要调试的地方写入s ...

  10. Java Web项目(Extjs)报错九

    1.Java Web项目(Extjs)报错九 具体报错如下: 三月 26, 2014 11:48:35 下午 org.hibernate.util.JDBCExceptionReporter logE ...