首页 > 代码库 > Spring第九弹—使用CGLIIB实现AOP功能与AOP概念解释

Spring第九弹—使用CGLIIB实现AOP功能与AOP概念解释

JDK自从1.3版本开始,就引入了动态代理,并且经常被用来动态地创建代理,原理之前我已经讲过。JDK的动态代理用起来非常简单,但它有一个限制,就是使用动态代理的对象必须实现一个或多个接口。如果想代理没有实现接口的继承的类,该怎么办?现在我们可以使用CGLIB包。

PS:需要引入com.springsource.net.sf.cglib-2.2.0.jar包。

CGLIB是一个强大的高性能的代码生成包。它广泛的被许多AOP的框架使用,例如:Spring AOP和dynaop,为他们提供方法的interception(拦截); 它的原理是对指定的目标类生成一个子类,并覆盖其中方法实现增强,但因为采用的是继承,所以不能对final修饰的类进行代理。 (CGLIB可以生成目标类的子类,并重写父类非final修饰符的方法。)

使用Cglib包生成代理的模板

 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public class CGLIBProxy implements MethodInterceptor {
 
private Object targetObject;//代理的目标对象
 
public Object createProxyInstance(Object targetObject){
 
this.targetObject targetObject;
 
Enhancer enhancer new Enhancer();//该类用于生成代理对象
 
enhancer.setSuperclass(this.targetObject.getClass());//设置父类
 
enhancer.setCallback(this);//设置回调用对象为本身
 
return enhancer.create();
 
}
 
public Object intercept(Object proxyMethod methodObject[args,MethodProxy methodProxythrows Throwable {
 
return methodProxy.invoke(this.targetObjectargs);
 
}
 
}

第一个参数是代理对像,第二和第三个参数分别是拦截的方法和方法的参数。通过使用java.lang.reflect.Method对象的一般反射调用或者使用net.sf.cglib.proxy.MethodProxy对象调用都可以完成对原方法的调用,但是通常net.sf.cglib.proxy.MethodProxy对象被首选使用,因为它更快。

PS:net.sf.cglib.proxy.MethodProxy应该是cglib生成用来代替Method对象的一个对象,使用MethodProxy比调用JDK自身的Method直接执行方法效率会有提升。

示例:

Service类:

 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package net.zmcheng.service;
 
public class PersonService {
private String name;
public PersonService(){
super();
}
public PersonService(String name){
this.name name;
}
public String getName({
return name;
}
 
public void setName(String name{
this.name name;
}
public void save(){
   System.out.println("我是save方法");
  }
 
}

Cglib动态代理工厂:

 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
package net.zmcheng.aop;
 
import java.lang.reflect.Method;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import net.zmcheng.service.PersonService;
public class CglibProxyFactory implements MethodInterceptor{
public Object targetObject;
public Object createProxyIntance(Object targetObject){
this.targetObject targetObject;
Enhancer enhancer new Enhancer();//该类用于生成代理对象
enhancer.setSuperclass(this.targetObject.getClass());//设置父类
enhancer.setCallback(this);//设置回调用对象为本身
return enhancer.create();//创建代理对象
}
 
//MethodInterceptor接口类似于jdk中的java.lang.reflect.InvocationHandler接口
// MethodInterceptor中的intercept方法同java.lang.reflect.InvocationHandler接口中的 invoke方法类似
public Object intercept(Object proxyMethod methodObject[argsMethodProxy methodProxy){//环绕通知
PersonService bean (PersonService)this.targetObject;
Object result null;
 
if(bean.getName()!=null){
//....advice()--->前置通知
 
try {
 
result method.invoke(targetObjectargs);
//..afteradvice()--->后置通知
 
catch (Exception e{
 
//....exceptionadvice()--->例外通知
 
e.printStackTrace();
}finally{
 
//finallyadvice();----->最终通知
}
 
}
return result;
}
}

测试类:

 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package net.zmcheng.test;
 
import org.junit.BeforeClass;
import org.junit.Test;
import net.zmcheng.aop.CglibProxyFactory;
import net.zmcheng.service.PersonService;
public class aopTest {
 
@BeforeClass
public static void setUpBeforeClass(throws Exception {
}
 
@Test
public void test({
CglibProxyFactory factory new CglibProxyFactory ();
PersonService service (PersonService)factory.createProxyIntance(new PersonService("zmc"));
service.save();
}
}

输出结果:我是save方法

AOP中的概念:

Aspect(切面):指横切性关注点的抽象即为切面,它与类相似,只是两者的关注点不一样,类是对物体特征的抽象,而切面横切性关注点的抽象.

joinpoint(连接点):所谓连接点是指那些被拦截到的点。在spring中,这些点指的是方法,因为spring只支持方法类型的连接点,实际上joinpoint还可以是field或类构造器)

Pointcut(切入点):所谓切入点是指我们要对那些joinpoint进行拦截的定义.

Advice(通知):所谓通知是指拦截到joinpoint之后所要做的事情就是通知.通知分为前置通知,后置通知,异常通知,最终通知,环绕通知

Target(目标对象):代理的目标对象

Weave(织入):指将aspects应用到target对象并导致proxy对象创建的过程称为织入.

Introduction(引入):在不修改类代码的前提下, Introduction可以在运行期为类动态地添加一些方法或Field.

Spring第九弹—使用CGLIIB实现AOP功能与AOP概念解释