使用cglib配合Annotation 实现一个AOP
先看代码后解释:
public interface AOPInterface {
public void BeforeMethod();
public void AfterMethod();
}
上面的是AOP的接口,包含了方法执行前和执行后的方法
public class Caller implements MethodInterceptor {
private AOPInterface Iaop;
public Object intercept(Object obj, Method method, Object[] args,MethodProxy proxy) throws Throwable {
Object result = null;
/**
* 当Annotation在类上方的时候,应该判断superclass是否有Annotation
* 因为cglib帮你创建出来的已经是动态继承了你的类,成了子类!!
* 关键!!
*/
if(obj.getClass().getSuperclass().isAnnotationPresent(InterceptorHandler.class)){
this.Iaop.BeforeMethod();
result = invokeMethod(obj,args,proxy); //方法在下面
this.Iaop.AfterMethod();
return result;
}else{
if(method.isAnnotationPresent(InterceptorHandler.class)){
this.Iaop.BeforeMethod();
result = invokeMethod(obj,args,proxy); //方法在下面
this.Iaop.AfterMethod();
return result;
}else{
return invokeMethod(obj,args,proxy);
}
}
}
private Object invokeMethod(Object obj,Object[] args,MethodProxy proxy) throws Throwable {
return proxy.invokeSuper(obj, args);
}
// get、set省略...
}
这个是cglib代理方法的调用类,为它加入了一个AOP接口的引用,使得方法调用前后可以灵活的改变
(有点类似于策略模式)
public class TestHandler implements AOPInterface {
public void AfterMethod() {
System.out.println("Good Bye!");
}
public void BeforeMethod() {
System.out.println("Hello!");
}
}
这个是真实的AOP处理类,实现了AOPInterface接口,只要实现了这个接口,就可以在AOP的时候调用
里面的方法 After和Before
@Retention(RetentionPolicy.RUNTIME)
@Target(value={ElementType.METHOD,ElementType.TYPE})
public @interface InterceptorHandler {
public Class<?> handlerClass();
}
这个是注解的开发!可以看到注解保持到RUNTIME,就可以用反射取得,
可以标注的地方为方法上(METHOD)和类上(类、接口、枚举都是使用TYPE类型)
唯一的属性是,处理这个AOP的类型
public class AOPFactory {
public Map<String,Class<?>> beansInfo;
/**
* 这个方法是通过配置取得Bean信息
* 我在此处就省略,直接取得目标Bean,
* 对真实扫描不懂可以看我的博客“取得包内的类”
*/
public AOPFactory(){
this.beansInfo = new HashMap<String, Class<?>>();
this.beansInfo.put("TrueClass", TrueClass.class);
this.beansInfo.put("TrueClass2", TrueClass2.class);
this.beansInfo.put("TestHandler", TestHandler.class);
}
/**
* 这个方法我也简化,直接使用手动装配
*/
public Object getBean(String beanName) throws InstantiationException, IllegalAccessException{
//取得Bean的类型
Class<?> clazz = this.beansInfo.get(beanName);
//装配AOP
AOPInterface handler = (AOPInterface)(this.beansInfo.get("TestHandler").newInstance());
Caller c = new Caller();
c.setIaop(handler);
//cglib代理创建者
Enhancer eh = new Enhancer();
eh.setSuperclass(clazz);
eh.setCallback(c);
//创建代理
return eh.create();
}
}
上面这个是AOP的工厂类,由于篇幅关系,我做了非常大的简化,自动扫描包,改为了手动装配
如果想要了解像Spring一样自动扫描包的功能,在我博客上也有,有兴趣可以看一下
public class TrueClass {
@InterceptorHandler(handlerClass=TestHandler.class)
public void meetMM(){
System.out.println("Just Go Around With MM!");
}
public void afterMeetMM(){
System.out.println("Go Home!");
}
}
@InterceptorHandler(handlerClass=TestHandler.class)
public class TrueClass2 {
public void BuySomeThing(){
System.out.println("我就要这些,多少钱?");
}
public void NoMoney(){
System.out.println("我忘带钱了");
}
}
上面两个类,是真实的业务类,是用来测试的,TrueClass类只有方法上有注解,而TrueClass2
类上有注解,代表了这个类的所有方法都被cglib拦截
下面是测试方法(JUnit4)
@Test
public void testAOP(){
AOPFactory factory = new AOPFactory();
try {
TrueClass tc = (TrueClass)factory.getBean("TrueClass");
tc.meetMM();
tc.afterMeetMM();
TrueClass2 tc2 = (TrueClass2)factory.getBean("TrueClass2");
tc2.BuySomeThing();
tc2.NoMoney();
} catch (Exception e) {
e.printStackTrace();
}
}
执行后输出的果是:
Hello!
Just Go Around With MM!
Good Bye!
Go Home!
Hello!
我就要这些,多少钱?
Good Bye!
Hello!
我忘带钱了
Good Bye!
可以看到我们注释上的方法都被拦截了,没有注释的就没有拦截(Go Home前后)
上面的方法要注意的地方再总结一下:
1)cglib方法代理方法的调用类(Caller)中 ,执行方法的函数不是invoke,而是invokeSuper
因为cglib动态继承了你的类,导致了invoke会不断执行Caller的方法,而不是代理类的
2)在判断类的上方是否有Annotation的时候
不是xxx.getClass.isAnnotationXXXXX()
而是xxx.getClass.getSuperClass.isAnnotationXXXXX()
原因也是cglib动态继承所造成的!
注:如果运行报错 请检查是否缺少asm jar包
感谢作者分享 转自:http://emavaj.blog.163.com/blog/static/133280557201003111711997/
分享到:
相关推荐
基于注解实现SpringAop基于注解实现SpringAop基于注解实现SpringAop
动态代理是实现AOP的一种常用技术,它允许在运行时创建代理对象,拦截对真实对象的调用,并在调用前后添加额外的行为。 在Java开发中,反射机制是实现动态代理的关键技术之一。反射提供了在运行时访问和操作类的...
基于代理实现AOP切面编程 基于代理的AOP实现主要涉及到两种代理方式:JDK动态代理和CGLIB代理。Spring会根据目标对象是否实现了接口来选择合适的代理方式。 - **JDK动态代理**:如果目标对象实现了至少一个接口,...
本篇文章将深入探讨如何通过Spring的注解方式实现AOP的细节。 首先,我们需要了解AOP的基本概念。AOP的核心是切面(Aspect),它封装了跨越多个对象的行为或责任。切点(Pointcut)定义了哪些方法会被通知(Advice...
下面我们将深入探讨Java动态代理的原理以及如何实现AOP功能。 ### 一、Java动态代理原理 Java中的动态代理主要通过`java.lang.reflect.Proxy`类和`java.lang.reflect.InvocationHandler`接口来实现。`Proxy`类用于...
在C#中,实现AOP的方法多种多样,以下将详细介绍几种常见的实现方式。 1. **静态织入**: 静态织入是在编译时完成的,它通过编译器或者编译插件(如PostSharp)在目标类的代码中插入拦截逻辑。这种方式的优点是...
拦截器是实现AOP的核心,它在方法调用前后执行自定义逻辑。 3. 创建拦截器:通过继承`IInterceptor`接口或使用`Unity.Interception`库中的`InterceptionBehavior`抽象类,我们可以创建自定义拦截器。例如,创建一个...
Spring 提供了两种方式来实现AOP代理:JDK动态代理和CGLIB代理。 1. **JDK动态代理**: - JDK动态代理基于Java的接口实现,适用于目标对象实现了接口的情况。Spring会为这个接口创建一个代理类,代理类在调用真实...
在C#中,实现AOP可以帮助开发者处理如日志记录、事务管理、性能度量等横切关注点,这些关注点通常会分散在应用程序的各个角落。C#实现的AOP框架可以通过动态代理、编译时织入或运行时织入等方式实现。 C#中常见的...
在net core2.2时,我当时就尝试过用autofac实现aop,但这次我不想用autofac,我用了一个更轻量级的框架,AspectCore。 用起来非常非常的简单,但一开始还是走了一点弯路,主要是网上都是net core3以下的教程,3以下...
Java动态代理实现AOP Java动态代理是实现Aspect Oriented Programming(AOP)的重要手段。在Java中,动态代理可以通过java.lang.reflect InvocationHandler接口和java.lang.reflect.Proxy类来实现。AOP的主要思想...
在.NET平台上实现AOP,我们可以借助于不同的库和技术,如PostSharp、Unity、Autofac等。下面我们将深入探讨.NET平台AOP的实现方法和应用。 首先,我们需要理解AOP的基本概念。AOP的核心是切面(Aspect),它封装了...
通过Spring的XML配置,我们可以灵活地定义和实现AOP通知,包括前置、后置、返回后、异常后以及环绕通知。这使得我们可以将横切关注点与业务逻辑分离,提高代码的可维护性和复用性。Spring的AOP功能强大且易于使用,...
本篇文章将探讨如何通过JDK动态代理实现Spring AOP的基础知识。 首先,我们要理解什么是JDK动态代理。在Java中,动态代理机制允许我们在运行时创建一个实现了特定接口的新类。这个新类的实例可以代理目标对象,执行...
Spring AOP实现方法之一:CGLIB 实现AOP功能
AOP(Aspect Oriented Programming,面向切面编程)是Spring框架中的一个重要特性,它提供了一种模块化和声明式的方式来处理...在实际项目中,结合使用这些注解可以实现各种复杂的切面功能,提升软件设计的质量和效率。
本篇将主要讨论如何通过注解方式来实现AOP编程。 首先,我们需要了解Spring中的核心注解。`@Aspect`是定义一个切面的注解,通常会定义在一个独立的类上。这个类将包含切点(Pointcut)和通知(Advice)。 切点是...
C#作为.NET框架的主要编程语言,提供了强大的支持来实现AOP,特别是在处理事务管理方面。事务是数据库操作的核心概念,确保数据一致性并能够在异常情况下进行回滚。 C#实现AOP事务的关键在于利用特性(Attribute)...
详细介绍了AOP的核心功能(拦截功能)在底层是如何实现的;介绍了两种实现AOP的动态代理:jdk动态代理和cglib动态代理,并详细描述了它们在代码层面的实现。附有必须的cglib.jar和asm.jar
在本项目中,我们将探讨如何通过配置文件实现Spring AOP,包括前置通知、后置通知以及拦截器的运用。 首先,我们需要理解Spring AOP的核心概念。切面(Aspect)是关注点的模块化,这些关注点定义了跨越多个对象的...