spring 的2大核心IOC和AOP,今天就来介绍一下AOP吧。。。
AOP,即是Aspect-Oriented—Programming,面向切面编程。面向方面编程(AOP)是面向对象编程(OOP)的一种扩展技术,能够很好的解决横切关注点问题以及相关的设计难题来实现松散耦合。AOP(Aspected Oriented Programming)是一种新兴的编程技术。它可以解决OOP和过程化方法不能够很好解决的横切(crosscut)问题,如:事务、安全、日志等横切关注。当未来系统变得越来越复杂,横切关注点就成为一个打问题的时候,AOP就可以很轻松的解决横切关注点这个问题,使得AOP编程成为。Spring 是基于J2EE的轻量级开源开发框架,其中Spring AOP组件实现了面向方面编程。
首先来介绍一下AOP的几个概念。
连接点(JoinPoint)是程序运行中某个阶段的点。如某个方法调用异常抛出等。
切入点(Pointcut)是连接点的集合,它是程序中需要注入的advice位置的集合。
通知(Advice)是某个连接点搜采用的处理逻辑。也就是向连接点注入的代码。
Spring的AOP主要是通过代理方式实现的。有2种代理机制:
1.基于jdk的动态代理。
2.基于CGLIB的动态代理。
这里先说一下代理的概念吧。
代理模式:给某一个对象提供代理对象,并由代理对象控制具体对象的引用。举个例子吧。我们买酒,不是直接从生产酒的工厂买的,而是通过代理商买的,这个代理的概念是差不多的。
下面来举个例子说明一下基于jdk的动态代理。
例子是从网上找的一个简单的。
public interface Hello {
Public void hello();
}
.import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
.import java.lang.reflect.Proxy;
.import org.Hello;
.public class SayHello implements Hello{
@Override
public void hello() {
// TODO Auto-generated method stub
System.out.println("hello");
}
static class MyInvocationHandler implements InvocationHandler{
private Object target;
public MyInvocationHandler(Object target){
this.target=target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
// TODO Auto-generated method stub
System.out.println(method.getName()+"-------start");
Object result=method.invoke(target, args);
System.out.println(method.getName()+"--------end");
return result;
}
}
static class ProxyFactory{
InvocationHandler h;
Class cls;
public ProxyFactory(String className,InvocationHandler h) throws ClassNotFoundException{
cls=Class.forName(className);
this.h=h;
}
public Object create(){
return Proxy.newProxyInstance(cls.getClassLoader(), cls.getInterfaces(), h);
}
}
public static void main(String[] args) throws ClassNotFoundException {
Hello s=new SayHello();
InvocationHandler h=new MyInvocationHandler(s);
ProxyFactory proxyFactory=new ProxyFactory(SayHello.class.getName(), h);
Hello sf=(Hello) proxyFactory.create();
sf.hello();
}
}
----------------会输出
hello-------start
hello--------end
jdk 的动态代理是用java.lang.reflect.proxy 下的类的。不懂可以查一下api文档。
有上面的例子可以看到这种代理被代理的类一定要实现一个接口的。但是如果一个类没有接口的话。那要怎么实现代理呢?这个时候spring就会采用CGLIB代理
下面来介绍一个CGLIB代理
cglib(Code Generation Library)是一个强大的,高性能,高质量的Code生成类库。它可以在运行期扩展Java类与实现Java接口。
cglib封装了asm,可以在运行期动态生成新的class。
cglib用于AOP,jdk中的proxy必须基于接口,cglib却没有这个限制。
cglib 包是通过动态的生生一个子类去覆盖搂腰代理类的不是finale的方法。并设置好callback,则原有类的每个方法调用就会转变成调用用户定义的拦截方法。
同样下面也举个例子吧。同样例子也是从网上找的。
public class MyClass {
public void method() {
System.out.println("MyClass.method()");
}
}
import java.lang.reflect.Method;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodProxy;
import net.sf.cglib.proxy.MethodInterceptor;
public class Test {
public static void main(String[] args) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(MyClass.class);
enhancer.setCallback( new MethodInterceptorImpl() );
MyClass my = (MyClass)enhancer.create();
my.method();
}
private static class MethodInterceptorImpl implements MethodInterceptor {
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
System.out.println(method);
proxy.invokeSuper(obj, args);
return null;
}
}
}
/*
javac -cp .;cglib-2.1.3.jar;asm-1.5.3.jar *.java
pause
java -cp .;cglib-2.1.3.jar;asm-1.5.3.jar Test
pause
*/
简单来说是使用cglib代理某个类,需要在Enhance对象中设置好基类,以及一系列回调函数。
关于springAOP的两种代理就先介绍到这里,至于在spring中怎么用?怎么配置?我们下次再探讨!