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 proxy, Method method, Object[] args,MethodProxy methodProxy) throws Throwable {

return methodProxy.invoke(this.targetObject, args);

}

}

第一个参数是代理对像,第二和第三个参数分别是拦截的方法和方法的参数。通过使用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 proxy, Method method, Object[] args, MethodProxy methodProxy){//环绕通知

PersonService bean = (PersonService)this.targetObject;

Object result = null;

if(bean.getName()!=null){

//....advice()--->前置通知

try {

result = method.invoke(targetObject, args);

//..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.

时间: 2024-10-23 00:09:06

Spring第九弹—使用CGLIIB实现AOP功能与AOP概念解释的相关文章

使用CGLIB实现AOP功能与AOP概念解释

使用CGLIB实现AOP功能 在Java里面,我们要产生某个对象的代理对象,这个对象必须要有一个特点,即这个对象必须实现一个接口,动态代理技术只能基于接口进行代理.有时候我们在做开发的时候,这个对象就没有实现接口,有人可能会说,它既然没有接口,那我就给它定义一个接口,这是不行的,因为有时候我们拿到一个对象,而这个对象是服务器产生给我们的,是服务器提供给我们的,又不是我们自己写的,动不动就给它定义一个接口,给它找个爸爸,哪那行呢?但我们现在要对它进行增强,这时用动态代理技术就不行了,动态代理技术只

使用 Spring 2.5 注释驱动的 IoC 功能

使用 Spring 2.5 注释驱动的 IoC 功能 原文链接 :http://www.ibm.com/developerworks/cn/java/j-lo-spring25-ioc/ 文中对Spring 2.5新引入的注解配置做了详细的讲解以及实例,包括 @Autowired  @Qualifier @Resource @PostConstruct 和 @PreDestroy <context:annotation-config/> <context:component-scan/&

使用 Spring 2.5 注释驱动的 IoC 功能(转)

基于注释(Annotation)的配置有越来越流行的趋势,Spring 2.5 顺应这种趋势,提供了完全基于注释配置 Bean.装配 Bean 的功能,您可以使用基于注释的 Spring IoC 替换原来基于 XML 的配置.本文通过实例详细讲述了 Spring 2.5 基于注释 IoC 功能的使用. 陈 雄华 ([email protected]), 技术总监, 宝宝淘网络科技有限公司 2008 年 2 月 28 日 内容 概述 注释配置相对于 XML 配置具有很多的优势: 它可以充分利用 J

Spring框架使用(控制反转,依赖注入,面向切面AOP)

参见:http://blog.csdn.net/fei641327936/article/details/52015121 Mybatis: 实现IOC的轻量级的一个Bean的容器 Inversion of control 控制反转:由容器控制程序之间的关系,不是程序代码操作 Depend Inject 依赖注入 Aspect oriented programming 面向切面编程 Spring能帮助我们根据配置文件创建及组装对象之间的依赖关系: Spring面向切面编程能帮助我们无耦合的实现日

SpringBoot中使用LoadTimeWeaving技术实现AOP功能

目录 1. 关于LoadTimeWeaving 1.1 LTW与不同的切面织入时机 1.2 JDK实现LTW的原理 1.3 如何在Spring中实现LTW 2. Springboot中使用LTW实现AOP的例子 3. 参考资料 1. 关于LoadTimeWeaving 1.1 LTW与不同的切面织入时机 AOP--面向切面编程,通过为目标类织入切面的方式,实现对目标类功能的增强.按切面被织如到目标类中的时间划分,主要有以下几种: 1.运行期织入 这是最常见的,比如在运行期通过为目标类生成动态代理

Spring 一二事(9) - xml 形式的 AOP

AOP在spring中是非常重要的一个 在切面类中,有5种通知类型: aop:before  前置通知 aop:after-returning  后置通知 aop:after  最终通知 aop:after-throwing  异常通知 aop:around  环绕通知 1 <bean id="personDAO" class="com.lee.spring002.aop.xml.PersonDAOImpl"></bean> 2 <be

java Instrument修改字节码实现aop功能

Agent工程2个类: public class MyAgent { /** * 该方法在main方法之前运行,与main方法运行在同一个JVM中 * 并被同一个System ClassLoader装载 * 被统一的安全策略(security policy)和上下文(context)管理 */ public static void premain(String agentOps, Instrumentation inst) { System.out.println("=========prema

你相信么,只需一个函数5行JS代码即可在Javascript中实现完整的AOP功能

你相信么,只需一个函数5行JS代码即可在Javascript中实现完整的AOP功能, 你相信么,在JavaScript只需一个函数5行代码即可实现完整的面向方面AOP编程功能.这5行代码的功能包括: 无限层次的函数无害拦截 函数执行前拦截 检查函数的参数值 重新设定函数的参数值 函数执行后拦截 检查函数执行后的返回结果 重新设定函数的返回结果 虽然动态函数式语言的效率是一个存在的问题,但是对于它的高度灵活性,简直让人令人惊叹不已,剧赞. 这个小小的函数源自于和爱明兄的一次讨论:在javascri

Java--简单的Spring AOP配置以及AOP事物管理,JDK/GCLib动态代理

一.看一下简单的通过XML的AOP配置 1.首先创建一个简单的Student类 public class Student { private Integer age; private String name; public void setAge(Integer age) { this.age = age; } public Integer getAge() { System.out.println("Age : " + age); return age; } public void