关键词:AOP、SOC、代理模式、动态代理。
上一话,我提到了一个重要的概念就是SOC,即关注点分离。为什么要分离关注点,因为这样可以让我们更加简单而富有条理的去处理这个繁杂的世界。AOP就是SOC的一种体现。
什么是AOP?
AOP全程是Aspect Oriented Programming意即面向切面编程。他并不是什么OOP的替代技术,只是OOP的一种延续。使用SOC的思想,去解耦,去降低问题的复杂度。那么,为什么要叫做面向切面编程呢?想想一下,当你在软件开发设计类的时候,会不会发现,有些逻辑或者功能,是每个类或者说大多数类都需要完成的呢?比如异常/错误处理,比如系统日志记录,比如持久化中的事务处理。与其一个一个的实现,为什么不能把他们单独提取出来加以处理呢。如果说把这些类平行的放在一起。这些公共的部分刚好并排在一起,能够一刀切下。可能这就是切面概念的由来,呵呵。AOP就是为了解决上述问题而出现的。
代理模式
为什么要提代理模式。因为AOP的广泛实现都是通过动态代理,而动态代理又不得不说代理模式。
代理模式,顾名思义,就是对一个类的访问,变为访问这个类的代理人。经由代理再访问这个类。(代理与被代理的类实现了相同的接口,因此客户感觉不到通过代理访问这个类和直接访问这个类的区别)
为什么需要代理呢,因为一个良好的设计不应该轻易的修改。这正是开闭原则的体现:一个良好的设计应该对修改关闭,对扩展开放。而代理正是为了扩展类而存在的。他可以控制对现有类(就是需要被代理的类)服务的访问,通俗的解释就是 可以拦截对于现有类方法的调用并做些处理。
而动态代理,是指在运行期动态的为指定的类生成其代理类。(需要相关的运行时编译技术,)
AOP如Spring的AOP实现就是以这种方式实现的。他使用动态生成的代理类拦截了现有类的“切点”。并进行控制,使得这些切面的逻辑完全与该类脱离,实现了关注点分离。
下面附上我用Javassist实现的简单动态代理。(Javassist是一个运行时编译库,他能动态的生成或修改类的字节码,类似的有ASM和CGLIB,大多数框架就是基于后者实现的)
package com.lifewool;
import javassist.CtMethod;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtConstructor;
import javassist.CtField;
import javassist.CannotCompileException;
import javassist.NotFoundException;
/**
* 基于Javassist动态生成字节码实现简单的动态代理
* Dynamic Proxy based on Javassist
* @author:godsong
* @version:1.01 2012/3/16
* */
public class DProxy {
/**
* 动态生成的代理类名前缀
* prefix name for Proxy
* */
private static final String PROXY_CLASS_NAME=".Gproxy$";
/**
* 代理类名索引 用于标示一个唯一的代理类(具体的代理类名为Gproxy$n)
* index for generate a unique proxy class
* */
private static int proxyIndex=1;
/**
* 代理拦截器(利用继承减少动态构造的字节码)
* Proxy interceptor(desingn for inherit)
* */
protected Interceptor interceptor;
/**
* Prohibit instantiation
* 利用私有构造函数阻止该类实例化
* */
private DProxy(){}
protected DProxy(Interceptor interceptor){
this.interceptor=interceptor;
}
/**
* 创建动态代理的工厂方法
* static factory method for create proxy
* @param targetClass :被代理的类型
* @param interceptor 拦截器实例
* @return 返回动态代理实例
* 它实现了targerClass的所有接口。
* 因此可以向上转型为这些之中的任意接口
* */
public static Object createProxy(Class<?> targetClass,Interceptor interceptor){
int index=0;
/*获得运行时类的上下文*/
ClassPool pool=ClassPool.getDefault();
/*动态创建代理类*/
CtClass proxy=pool.makeClass(targetClass.getPackage().getName()+PROXY_CLASS_NAME+proxyIndex++);
try{
/*获得DProxy类作为代理类的父类*/
CtClass superclass=pool.get("com.lifewool.DProxy");
proxy.setSuperclass(superclass);
/*获得被代理类的所有接口*/
CtClass[] interfaces=pool.get(targetClass.getName()).getInterfaces();
for(CtClass i:interfaces){
/*动态代理实现这些接口*/
proxy.addInterface(i);
/*获得结构中的所有方法*/
CtMethod[] methods=i.getDeclaredMethods();
for(int n=0;n<methods.length;n++){
CtMethod m=methods[n];
/*构造这些Method参数 以便传递给拦截器的interceptor方法*/
StringBuilder fields=new StringBuilder();
fields.append("private static java.lang.reflect.Method method"+index);
fields.append("=Class.forName(\"");
fields.append(i.getName());
fields.append("\").getDeclaredMethods()[");
fields.append(n);
fields.append("];");
/*动态编译之*/
CtField cf=CtField.make(fields.toString(), proxy);
proxy.addField(cf);
GenerateMethods(pool,proxy,m,index);
index++;
}
}
/*创建构造方法以便注入拦截器*/
CtConstructor cc=new CtConstructor(new CtClass[]{pool.get("com.lifewool.Interceptor")}, proxy);
cc.setBody("{super($1);}");
proxy.addConstructor(cc);
//proxy.writeFile();
return proxy.toClass().getConstructor(Interceptor.class).newInstance(interceptor);
}catch(Exception e){
e.printStackTrace();
return null;
}
}
/**
* 动态生成生成方法实现(内部调用)
* */
private static void GenerateMethods(ClassPool pool,CtClass proxy,CtMethod method,int index){
try {
CtMethod cm=new CtMethod(method.getReturnType(), method.getName(), method.getParameterTypes(), proxy);
/*构造方法体*/
StringBuilder mbody=new StringBuilder();
mbody.append("{super.interceptor.intercept(this,method");
mbody.append(index);
mbody.append(",$args);}");
cm.setBody(mbody.toString());
proxy.addMethod(cm);
} catch (CannotCompileException e) {
e.printStackTrace();
}
catch (NotFoundException e){
e.printStackTrace();
}
}
}
客户端代码
public interface Interface {
void Action(int a);
}
class clazz implements Interface{
@Override
public void Action(int a) {
System.out.println("do Action"+a);
}
}
class MyInterceptor implements Interceptor{
Object proxyed;
public MyInterceptor(Object i){
proxyed=i;
}
@Override
public int intercept(Object instance, Method method, Object[] Args) {
try {
System.out.println("before action");
method.invoke(this.proxyed, Args);
System.out.println("after action");
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
return 0;
}
}
public class test {
/**
* @param args
*/
public static void main(String[] args) {
clazz c=new clazz();
Interface i=(Interface)DProxy.createProxy(clazz.class, new MyInterceptor(c));
i.Action(123);
}
}
结果:
before action
do Action123
after action
分享到:
相关推荐
动态代理是实现AOP的一种常用技术,它允许在运行时创建代理对象,拦截对真实对象的调用,并在调用前后添加额外的行为。 在Java开发中,反射机制是实现动态代理的关键技术之一。反射提供了在运行时访问和操作类的...
在Spring中,AOP主要通过两种动态代理技术实现:JDK动态代理和CGLIB动态代理。 首先,让我们详细了解一下JDK动态代理。JDK动态代理基于Java的接口实现,它适用于目标对象实现了至少一个接口的情况。在运行时,JDK...
总结来说,Spring AOP基于JDK动态代理的实现,允许我们以非侵入式的方式添加切面逻辑,提高了代码的组织性和模块化。通过理解JDK动态代理的工作原理和Spring AOP的相关概念,我们可以更好地利用这一强大功能,提升...
总结来说,Spring AOP的Schema配置是实现面向切面编程的一种方式,它通过XML定义切面、切入点和通知,使得非侵入式的关注点分离成为可能。通过熟练掌握这一技术,开发者可以更好地组织代码,提升代码的可维护性和可...
基于注解实现SpringAop基于注解实现SpringAop基于注解实现SpringAop
本项目旨在通过Java的动态代理技术实现面向切面编程(AOP),涵盖了静态代理、JDK动态代理、CGLIB动态代理、AspectJ以及基于instrumentation的动态代理等多种实现方式。通过这些实现方式,可以在不修改原有代码的...
AOP动态代理描述了Spring AOP中使用Java高级技术功能实现的动态代理,为Spring IOC等高级开发实现了逻辑功能;
Java动态代理实现AOP Java动态代理是实现Aspect Oriented Programming(AOP)的重要手段。在Java中,动态代理可以通过java.lang.reflect InvocationHandler接口和java.lang.reflect.Proxy类来实现。AOP的主要思想...
Spring框架是AOP实现的一个典范,它提供了两种主要的动态代理方式:JDK动态代理和CGLib动态代理。 **JDK动态代理**: JDK动态代理基于Java的反射API实现,适用于接口代理。当目标对象实现了至少一个接口时,Spring...
Spring AOP提供了基于代理的实现,可以在不修改原始代码的情况下,为业务方法添加额外的功能。此外,它还支持基于注解的切面定义,使得AOP的使用更加简洁。 5. **对比静态代理**:动态代理相比静态代理(手动编写...
总的来说,Java分页、动态代理和AOP是Java开发中的关键技术,它们能帮助我们构建出更加高效、可维护的Web应用程序。在实际项目中,理解并熟练掌握这些技术,将大大提升我们的开发效率和代码质量。
动态代理则是Spring AOP实现的核心技术之一,它允许我们在运行时创建具有额外行为的对象。下面将详细阐述Spring AOP的配置以及动态代理的实现。 一、Spring AOP基础知识 1. **什么是AOP**:AOP是一种编程范式,...
总结来说,动态代理是AOP的核心实现手段之一,它使得我们可以无侵入地在原有业务代码基础上添加功能,提高了代码的可维护性和可扩展性。无论是JDK动态代理还是CGLIB,都是为了在运行时动态地创建代理对象,从而实现...
在IT行业中,Spring框架是Java企业级应用开发的首选,而Spring AOP(面向切面编程)则是其核心特性之一,用于实现横切关注点的模块化,如日志、事务管理等。@AspectJ是Spring AOP的一种注解驱动方式,它极大地简化了...
总的来说,Spring AOP 通过动态代理技术实现了切面的插入,使得我们可以对代码进行非侵入式的增强,提高了代码的复用性和可维护性。无论是 JDK 动态代理还是 CGLIB 动态代理,它们的核心都是在方法调用时插入额外的...
1. **JDK动态代理**:基于接口的代理,如果目标对象实现了接口,Spring会使用`java.lang.reflect.Proxy`创建代理对象。 2. **CGLIB动态代理**:如果目标对象没有实现接口,Spring会使用CGLIB库来创建代理对象。CGLIB...
总结来说,Spring AOP通过动态代理实现了面向切面编程,利用反射在运行时生成代理对象并插入通知代码。这种设计让开发者能够专注于业务逻辑,而不必关心横切关注点的实现细节,提高了代码的可维护性和复用性。理解...
基于springmvc实现文件上传下载 基于AOP的日志功能基于springmvc实现文件上传下载 基于AOP的日志功能基于springmvc实现文件上传下载 基于AOP的日志功能基于springmvc实现文件上传下载 基于AOP的日志功能基于...
总结来说,JDK动态代理适合处理实现了接口的对象,CGLIB适用于没有接口或者对性能要求较高的情况,而javassist提供了更灵活的字节码操作,适用于更复杂的场景。理解并掌握这三种动态代理技术,对于提升Java编程的...