Spring AOP详细介绍(一)
一直有个想法,想写一些文章记录下工作和学习中的一些心得。最近刚好在回顾Spring方面的东西,Spring Aop是Spring框架中很重要的一个功能。下面介绍下AOP(面向切面)。
AOP称为面向切面编程,在程序开发中用来解决一些系统层面上的问题,比如日志,事务,权限等。
一 AOP的基本概念
(1) Aspect(切面):通常是一个类,里面可以定义切入点和通知
(2) JointPoint(连接点):程序执行过程中明确的点,一般是方法的调用
(3) Advice(通知):AOP在特定的切入点上执行的增强处理,有before,after,afterReturning,afterThrowing,around
(4) Pointcut(切入点):就是带有通知的连接点,在程序中主要体现为书写切入点表达式
(5) Target Object(目标对象):被一个或者多个切面所通知的对象
(6) Weaving(织入):把切面连接到其他的应用程序类或者对象上,并创建一个被通知的对象,分为:编译时织入、类加载时织入和执行时织入。
二 示例
- 例子1(脑残方法)
先写一个接口 :
public interface Animal {
public void run();
}
再写一个实现类:
public class AnimalImp implements Animal {
public void run() {
System.out.println("啪啪啪啪啪啪");
}
private void before(){
System.out.println("before");
}
private void after(){
System.out.println("after");
}
}
在实现类中before()和after()方法都是硬编码,如果每个类都这么写也太傻了吧,代码review时等着被骂吧,哈哈。
- 例子2(静态代理)
如果你刚刚学Java,可能还没学过什么设计模式,后面我也会写一些关于设计模式的总结。上面那种写法最简单地方法就是用静态代理模式,什么是代理呢,知道火车票代售点吧,代售点就是代理火车站买火车票的。说简单点老婆的代理就是小三,哈哈,扯远了。单独为AnimalImp写一个代理类:
public class AnimalProxy implements Animal {
private AnimalImp animalImp;
public AnimalProxy(AnimalImp animalImp) {
this.animalImp = animalImp;
}
public void run() {
before();
animalImp.run();
after();
}
private void before(){
System.out.println("before");
}
private void after(){
System.out.println("after");
}
}
好吧,聪明的你肯定会觉得这样,每个类都写一个代理类,那么工作量不是剧增吗,有没有一种只写一个代理类的方法呢。有肯定是有的,那就要用到动态代理了。动态代理有JDK代理和CGLIB代理。
- 例子3(动态代理)
3.1 JDK代理
JDK代理是JDK提供的,JDK代理的目标类需要实现接口。
public class JDKDynamicProxy implements InvocationHandler {
public JDKDynamicProxy(Object target) {
this.target = target;
}
private Object target;
public <T> T getProxy() {
return (T) Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
before();
Object result = method.invoke(target, args);
after();
return result;
}
private void before() {
System.out.println("Before");
}
private void after() {
System.out.println("After");
}
}
代码跑一下:
public class JDKClient {
public static void main(String[] args) {
Animal animal = new JDKDynamicProxy(new AnimalImp()).getProxy();
animal.run();
}
}
3.2 CGLIB代理
JDK提供的动态代理只能代理接口,不能代理没有实现接口的类。我们可以使用开源的CGLIB类库来实现动态代理。
public class CGLIBDynamicProxy implements MethodInterceptor {
private static CGLIBDynamicProxy instance = new CGLIBDynamicProxy();
private CGLIBDynamicProxy() {
}
public static CGLIBDynamicProxy getInstance(){
return instance;
}
public <T> T getProxy(Class<T> cls){
return (T) Enhancer.create(cls,this);
}
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
before();
Object result = methodProxy.invokeSuper(o,objects);
after();
return result;
}
private void before() {
System.out.println("Before");
}
private void after() {
System.out.println("After");
}
}
- 例子4(Spring AOP)
当然Spring AOP是这篇文章的重点啦。要上班咯,先写这么点。待续。。。