spring里面有个概念叫aop(面向切面编程),很好很强大又很让人费解,很多开发人员会用并且天天挂在嘴边但是不理解其核心原理,今天周末有空,我想用一个小系列的文章给大家把aop分析清楚。要理解aop,首先要掌握java中的代理模式。
在日常生活中,会遇到各种各样的中介机构,比如猎头公司,律师事务所,婚姻介绍所,房产公司等。在这些单位工作的人员均可称为代理人。代理人的共同特征是可以代替委托人去和第三方通信。譬如:律师代替委托人打官司,猎头代替委托人物色人才,红娘代替委托人寻找对象,房产代理人代替委托人出租房屋。
代理人可以在第三方和委托人之间转发或过滤消息,但是不能取代委托人的任务。譬如你要找女朋友,委托你一要好的哥们去帮你物色,结果被他给物色了。这就不叫代理。
代理模式的作用是:为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个客户不想或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。
代理模式一般涉及到的角色有:
抽象角色:声明真实对象和代理对象的共同接口;
代理角色:代理对象角色内部含有对真实对象的引用,从而可以操作真实对象,同时代理对象提供与真实对象相同的接口以便在任何时刻都能代替真实对象。同时,代理对象可以在执行真实对象操作时,附加其他的操作,相当于对真实对象进行封装。
真实角色:代理角色所代表的真实对象,是我们最终要引用的对象。
我们来看个例子:
package com.wepull.aop.staticProxy;
/**
* @author leno
*抽象角色
*/
public interface IHello {
String greeting(String who);
}
package com.wepull.aop.staticProxy;
/**
* @author leno
*真实角色
*/
public class HelloImpl implements IHello {
public String greeting(String who) {
System.out.println("greeting method is invoked.....");
return "hello,"+who;
}
}
试想一下,如果这时候我们要对问候的业务逻辑方法进行日志记录。我们当然可以这样做:
package com.wepull.aop.staticProxy;
/**
* @author leno
*真实角色
*/
public class HelloImpl implements IHello {
private Logger logger = Logger.getLogger(this.getClass().getName());
public void log(String message)
{
logger.log(Level.INFO, message);
}
public String greeting(String who) {
log( "starting...");
System.out.println("greeting method is invoked.....");
log("stopping...");
return "hello,"+who;
}
可问题来了,项目经理发话,不容许修改现存的类的实现。怎么办?这时候我们就要就想到代理模式了。我们再加一个代理类:
静态代理类:
package com.wepull.aop.staticProxy;
import java.util.logging.Level;
import java.util.logging.Logger;
public class HelloLoggerProxy implements IHello {
private Logger logger = Logger.getLogger(this.getClass().getName());
private IHello helloImpl;
public HelloLoggerProxy(IHello helloImpl) {
super();
this.helloImpl = helloImpl;
}
public String greeting(String who) {
log( "starting...");
String hello = helloImpl.greeting(who);
log("stopping...");
return hello;
}
public void log(String message)
{
logger.log(Level.INFO, message);
}
}
客户端测试代码:
package com.wepull.aop.staticProxy;
public class TestStaticProxy {
public static void main(String[] args) {
IHello hello = new HelloLoggerProxy(new HelloImpl());
hello.greeting("leno");
}
}
由以上代码可以看出,客户实际需要调用的是HelloImpl类的greeting()方法,现在用HelloLoggerProxy来代理HelloImpl类,同样达到目的,同时还在方法调用的前后都做了日志记录。这就是静态代理。
但是,如果要按照上述的方法使用代理模式,那么真实角色必须是事先已经存在的,并将其作为代理对象的内部属性。但是实际使用时,一个真实色必须对应角一个代理角色,如果大量使用会导致类的急剧膨胀;而且,如果项目中要做日志的类有100个,每个类里面有100个方法。重复代码就太可怕了。有人说,不怕,我就一愚公。好,有天项目经理突然要求修改做日志的方式,你再看看这些方法,估计撞墙的心都有了。那怎么办?我们就改用动态代理。
JDK1.3以后提供了动态代理的支持,程序员通过实现java.lang.reflect.InvocationHandler接口提供一个执行处理器,然后通过java.lang.reflect.Proxy得到一个代理对象,通过这个代理对象来执行商业方法,在商业方法被调用的同时,执行处理器会被自动调用。
动态代理类:
package com.wepull.aop.dynamicProxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.logging.Level;
import java.util.logging.Logger;
public class DynamicLoggerProxy implements InvocationHandler {
private Logger logger = Logger.getLogger(this.getClass().getName());
private Object delegate;
@SuppressWarnings("unchecked")
public Object bind(Object delegate)
{
this.delegate = delegate;
Class cls = delegate.getClass();
return Proxy.newProxyInstance(cls.getClassLoader(), cls.getInterfaces(), this);
}
public Object invoke(Object o, Method method, Object[] args)
throws Throwable {
log( "starting...");
Object obj = method.invoke(delegate, args);
log("stopping...");
return null;
}
public void log(String message)
{
logger.log(Level.INFO, message);
}
}
客户端测试代码:
package com.wepull.aop.dynamicProxy;
public class TestDynamicProxy {
public static void main(String[] args) {
IHello hello = (IHello) new DynamicLoggerProxy().bind(new HelloImpl());
hello.greeting("leno");
}
}
大家看到,一个动态代理类就代替了无数个静态代理类。一劳永逸。这里涉及到一些java反射的知识,我会在以后单独讲述。
java的动态代理非常实用和强大,可它有一个前提,需要我们的处理业务逻辑的类必须至少实现一个接口,虽然面向接口编程是
需要提倡的,但如果我们有些现存的类就是没有实现接口,那如何代理呢?这就需要CGLIB的帮助了。继续改进我们的代码:
没有实现任何接口的类:
package com.wepull.aop.cglibProxy;
public class Hello{
public void greeting(String who) {
System.out.println("hello,"+who);
}
}
CGLIB代理类:
package com.wepull.aop.cglibProxy;
import java.lang.reflect.Method;
import java.util.logging.Level;
import java.util.logging.Logger;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
public class CGLIBLoggerProxy implements MethodInterceptor {
private final Logger logger = Logger.getLogger(this.getClass().getName());
public Object bind(Object delegate)
{
Enhancer enhancer = new Enhancer();
enhancer.setCallback(this);
enhancer.setSuperclass(delegate.getClass());
return enhancer.create();
}
public Object intercept(Object o, Method method, Object[] args,
MethodProxy proxy) throws Throwable {
log( "starting...");
proxy.invokeSuper(o, args);
log("stopping...");
return null;
}
public void log(String message)
{
logger.log(Level.INFO,message);
}
}
客户端测试代码:
package com.wepull.aop.cglibProxy;
public class TestCGLIBProxy {
public static void main(String[] args) {
Hello hello = (Hello) new CGLIBLoggerProxy().bind(new Hello());
hello.greeting("leno");
}
}
好了,有了动态代理和CGLIB,那我们就可以给任何实际的类提供代理了。从而可以在我们的代理类中加入一些与业务逻辑无关的系统级的功能服务,如:日志记录,事务处理,安全管理等。而且不会影响到我们现有的系统。看起来似乎很完美了。但是且慢,如果我们的应用中有些需要这些系统级的功能服务,而有些又不需要呢?如果把代码写死了显然达不到我们的要求。怎么办?这时候就要用到一个非常重要的思想:用配置代替编码。
[转]
http://blog.csdn.net/lenotang/archive/2008/06/15/2551348.aspx
分享到:
相关推荐
Spring AOP(Aspect Oriented Programming,面向切面编程)是Spring框架的重要组成部分,它提供了一种在不修改源代码的情况下,对程序进行功能增强的技术。这个"spring aop jar 包"包含了实现这一功能所需的类和接口,...
在`springAop1`这个压缩包中,可能包含了一个简单的应用示例,展示了如何定义一个切面类,以及如何在该类中定义通知方法。例如,我们可能会看到一个名为`LoggingAspect`的类,其中包含了`@Before`注解的方法,用于在...
Spring AOP,全称为Aspect Oriented Programming,是面向切面编程的一种编程范式,它是对传统的面向对象编程(OOP)的一种补充。在OOP中,核心是对象,而在AOP中,核心则是切面。切面是关注点的模块化,即程序中的...
本文将基于"LYFspringAOP系列:自己写的springAOP例子"进行深入讲解。 首先,了解AOP的基本概念。AOP是一种编程范式,旨在解决程序中分散的、与业务逻辑不直接相关的部分,如日志记录、事务管理、性能监控等。通过...
1. **代理**:Spring AOP支持两种类型的代理:JDK动态代理和CGLIB代理。JDK代理用于实现了接口的类,而CGLIB代理则用于没有接口或不希望使用接口的类。代理对象在调用目标方法时会执行切面逻辑。 2. **织入**:织入...
Spring AOP(面向切面编程)是Spring框架的核心特性之一,它允许开发者在不修改源代码的情况下,通过插入切面来增强或改变程序的行为。在本教程中,我们将深入探讨Spring AOP的不同使用方法,包括定义切点、通知类型...
现在,我们回到主题——"springaop依赖的jar包"。在Spring 2.5.6版本中,使用Spring AOP通常需要以下核心jar包: - `spring-aop.jar`:这是Spring AOP的核心库,包含了AOP相关的类和接口。 - `spring-beans.jar`:...
spring-aop-1.1.1.jar spring-aop-1.2.6.jar spring-aop-1.2.9.jar spring-aop-2.0.2.jar spring-aop-2.0.6.jar spring-aop-2.0.7.jar spring-aop-2.0.8.jar spring-aop-2.0.jar spring-aop-2.5.1.jar spring-aop-...
1. **aspectj-1.7.3.jar**:这是AspectJ库的核心部分,提供了AOP语言支持,包括AspectJ编译器和运行时库。AspectJ是Java平台上的一个开源项目,它扩展了Java语言,支持声明式地编写横切关注点。通过AspectJ,我们...
Spring AOP 是一种面向切面编程的技术,它允许我们在不修改源代码的情况下,对应用程序的特定部分(如方法调用)进行增强。在 Spring 中,AOP 的实现主要依赖于代理模式,有两种代理方式:JDK 动态代理和 CGLIB 动态...
1. **非侵入性**:Spring AOP的设计理念是非侵入性的,这意味着开发人员无需修改现有代码就可以添加新的功能。这一点极大地降低了代码的耦合度。 2. **轻量级**:与一些需要预编译器的AOP框架不同,Spring AOP无需...
3、对spring aop认识模糊的,不清楚如何实现Java 自定义注解的 4、想看spring aop 注解实现记录系统日志并入库等 二、能学到什么 1、收获可用源码 2、能够清楚的知道如何用spring aop实现自定义注解以及注解的逻辑...
**Spring AOP 实现机制详解** Spring AOP(面向切面编程)是Spring框架的核心特性之一,它允许程序员在不修改源代码的情况下,通过“切面”来插入额外的业务逻辑,如日志、事务管理等。AOP的引入极大地提高了代码的...
基于注解实现SpringAop基于注解实现SpringAop基于注解实现SpringAop
Spring AOP(面向切面编程)是Spring框架的重要组成部分,它提供了一种模块化和声明式的方式来处理系统中的交叉关注点,如日志、事务管理等。在Java应用中,AOP通过代理模式实现了切面编程,使得我们可以将业务逻辑...
1. aopalliance-1.0.jar:这是一个非常基础的AOP库,定义了AOP的核心接口,如`org.aopalliance.intercept.MethodInterceptor`和`org.aopalliance.aop.Advice`,这些接口为不同的AOP框架提供了统一的交互方式。Spring...
Spring AOP 和 Spring IOC 是 Spring 框架的两个核心组件,它们对于任何基于 Java 的企业级应用开发都至关重要。Spring AOP(面向切面编程)允许开发者在不修改源代码的情况下,通过“切面”来插入新的行为或增强已...
面向切面编程(AOP)是一种编程范式,旨在将横切关注点(如日志、安全等)与业务逻辑分离,从而提高模块化。...利用Java反射机制和Spring AOP框架,开发者可以方便地实现AOP,从而提升代码的模块化和可维护性。
Spring AOP(面向切面编程)是Spring框架的重要组成部分,它提供了一种强大的方式来实现横切关注点,如日志、事务管理、安全性等,从而解耦应用程序的核心业务逻辑。在Spring AOP中,关注点被模块化为独立的“切面”...
Spring AOP(面向切面编程)是Spring框架的重要组成部分,它提供了一种模块化和抽象化的方法来处理系统中的交叉关注点,如日志、事务管理、安全性等。本学习笔记将深入探讨Spring AOP的核心概念、工作原理以及实际...