前文讲了, 可以利用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. Hibernate学习(二)保存数据

    package cn.lonecloud.test; import java.util.Date; import org.hibernate.HibernateException; import or ...

  2. network programming-简单的TCP客户服务器编程

    简单的TCP程序客户端流程:创建套接字(套接字用IP地址:端口号)表示)socket()->请求连接connect()->交换数据 send()/recv()->关闭连接 close ...

  3. 基础--Linux环境下一键部署 lnmp

    1. 通过x-shell 或者 putty 登录服务器 2. 下载lnmp一键安装包 >wget -c http://soft.vpser.net/lnmp/lnmp1.4.tar.gz  # ...

  4. Linux传统Huge Pages与Transparent Huge Pages再次学习总结

      Linux下的大页分为两种类型:标准大页(Huge Pages)和透明大页(Transparent Huge Pages).Huge Pages有时候也翻译成大页/标准大页/传统大页,它们都是Hu ...

  5. JAVA的helloworld

    java环境设置------------- 在环境变量中设置以下三个变量:JAVA_HOME=C:\j2sdk1.4.1 //可以改为相应的目录CLASSPATH=%JAVA_HOME%\lib\to ...

  6. 嵌入式Linux引导过程之1.1——Xloader的xloader.lds

    本文中的所有代码版本都是基于ST的SpearPlus开发板的. xloader是在系统上电之后,执行完ROM中的frimware后最先开始执行的用户程序,它的体积很小,执行的功能也很简单,主要是对系统 ...

  7. linux之x86裁剪移植---grub 识别文件系统

    grub主要作用是找到内核(kernel)与部分核心模块的镜像(initrd,主要是sata硬盘驱动之类的模块),把它们导入内存中运行.kernel与initrd放在文件系统中,因此grub必须有识别 ...

  8. php 连接mssql

    以前用的都是mysql,今天突然想用下mssql,起先用的是sql server200. 第一种方法 打开mssql.dll拓展.然后把mssql.secure_connection = off改为o ...

  9. dojo单柱状图

    dojo单柱状图 1.dojo单柱状图源码 column.html: <!DOCTYPE HTML> <html lang="en"> <head&g ...

  10. JSP中的编译指令和动作指令的区别

    JSP中的编译指令和动作指令的区别 1.编译指令是通知Servlet引擎的处理消息,而动作指令只是运行时的脚本动作 2.编译指令是在将JSP编译成Servlet时起作用,而动作指令可替换成JSP脚本, ...