声明:所有的5分钟系列博客都停留在使用的基础上,具体原理,并没有深入探讨,供项目中快速开发使用。
AOP 有多重要,我们在做项目是经常会碰到,权限验证,用户在线验证,数据的事物管理,还有其他个性化的需求里面。使用aop能大大的减少代码的重复性,写出更加符合正常人逻辑的代码!
第一种配置方法
在有spring的项目中简单的使用AOP 如下配置就ok了。例子:
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:context="http://www.springframework.org/schema/context" xmlns:util="http://www.springframework.org/schema/util" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" default-autowire="byName" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.2.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd"> <aop:config proxy-target-class="true"> <aop:advisor advice-ref="checkAdvice" pointcut="execution(* com.tt.doodoo.forum.controller..*(..))" /> </aop:config> <bean id="checkAdvice" class="com.tt.doodoo.forum.utils.CheckAuthor"/>
java代码:
import java.lang.reflect.Method;
import org.springframework.aop.MethodBeforeAdvice;
public class CheckAuthor implements MethodBeforeAdvice {
/**
* 此处处理登录信息
*/
public void before(Method method, Object[] args, Object target)
throws Throwable {
System.out.println("--------testBeforeAdvice------------");
}
}
当然这是最简单的方式,在每个Controller里面的每个方法执行之前都会调用这个方法,当然修改execution(* com.tt.doodoo.forum.controller..*(..))可以通过通配符来匹配各种方法名进行过滤。
第二种配置方法
如果以上spring提供的这种方法不喜欢的话,那就用另外一种AspectJ也给您提供的简单的annotation进行简单的配置,不过这里需要引入AspectJ提供的2个jar包,aspectjtools.jar aspectjweaver.jar.
配置如下
你的bean.xml里面只需要简单声明了
<!-- 打开AOP注解配置(支持) -->
<aop:aspectj-autoproxy/>
package spring.aop.interceptor;
import org.aspectj.lang.annotation.Aspect;
@Aspect
public class MyInterceptor {
2.声明切入点 ---拦截
@Pointcut("execution(* spring.aop.annotation..*.*(..))")
public void anyMethod(){}//设置切入点(也就是说这个anyMethod()方法来代替切入的方法)
//切入点:第一个*指的是对于任意返回类型,接下来spring.aop.annotation 包
..指的是:本包或者字包里面,*这里指的是任意类,然后接下来*指的是任意方法(..)指的是任意参数
3.设置前置通知
@Before("anyMethod()")
//拦截方法,在执行前先执行anyMethod()
public void doAccessCheck(String name){
//这个是前置通知的方法,在调用bean实例方法前
System.out.println("这是前置通知"+name);
}
}
如果需要参数的话这么传
@before("target(com.tt.doodoo.xxxController)&&args(name,age)")
public void bindlParams(String name,int age)(){
//
}
ok.相信这俩中方法能过满足您的需求了。
3 动态代理
就这么草草完事是不是很不爽,那我们再来看看他的简单原理。就是使用了动态代理而已。动态代理不难,我就只把代码贴出来了。
3.1 JDK 动态代理(只支持接口)
package test.proxy;
/**
接口
**/
public interface Buy {
void buyNoteBook(int money);
void buyHouse(int money);
void buyCar(int money);
}
实现类
package test.proxy;
public class Buyshow implements Buy {
public void buyCar(int money) {
System.out.println("spend "+ money +"RMB buy Car");
}
public void buyHouse(int money) {
System.out.println("spend "+ money +"RMB buy House");
}
public void buyNoteBook(int money) {
System.out.println("spend "+ money +"RMB buy NoteBook");
}
}
jdk代理类
package test.proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
/**
* jdk 动态代理
* @author jiuyuehe
*
*/
public class BuyPrivateHandler implements InvocationHandler {
/**
* 目标对象类!
*/
private Object target;
public BuyPrivateHandler(Object target) {
this.target = target;
}
/**
* 实现 InvocationHandler 的invoke方法。
*/
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
/**
* 方法之前 干什么
*/
System.out.println("为了 "+target.getClass().getName()+"."+method.getName());
Object obj = method.invoke(target, args);
System.out.println("终于 "+target.getClass().getName()+"."+method.getName());
/**
* 方法之后干什么
*/
return obj;
}
}
测试类
package test.proxy;
import java.lang.reflect.Proxy;
import org.springframework.aop.aspectj.annotation.AspectJProxyFactory;
/**'
* jdk 动态代理
* @author jiuyuehe
*
*/
public class ProxyTest {
public static void main(String[] args) {
// jdkProxy();
// cglibProxy();
aspectProxy();
}
private static void aspectProxy(){
Buy b = new Buyshow();
AspectJProxyFactory factory = new AspectJProxyFactory();
factory.setTarget(b);
factory.addAspect(AspectJForBuy.class);
Buy proxy = factory.getProxy();
proxy.buyCar(50000);
proxy.buyHouse(30000);
proxy.buyNoteBook(52513);
}
private static void cglibProxy(){
CglibProxy proxy = new CglibProxy();
Buyshow show = (Buyshow)proxy.getProxy(Buyshow.class);
show.buyCar(500000);
show.buyHouse(30);
show.buyNoteBook(63000);
}
private static void jdkProxy() {
Buy b = new Buyshow();
//将业务目标与横切面,织到一起
BuyPrivateHandler handler = new BuyPrivateHandler(b);
//给织在一起的横切面对象创建一个代理的实例。
//这里只能给接口 创建代理实例
Buy proxy = (Buy) Proxy.newProxyInstance(b.getClass().getClassLoader(),
b.getClass().getInterfaces(), handler);
proxy.buyCar(300000);
proxy.buyHouse(550000);
proxy.buyNoteBook(10000);
}
}
3.2 cglib 动态代理,支持普通类
package test.proxy;
import java.lang.reflect.Method;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
/**
* cglib 动态代理
* @author jiuyuehe
*
*/
public class CglibProxy implements MethodInterceptor {
private Enhancer enhancer = new Enhancer();
public Object getProxy(Class clazz){
//设置需要创建子类的类
enhancer.setSuperclass(clazz);
enhancer.setCallback(this);
//通过字节码技术动态创建子类实例
return enhancer.create();
}
//拦截父类所有方法的调用
public Object intercept(Object obj, Method method, Object[] args,
MethodProxy proxy) throws Throwable {
System.out.println("为了 "+obj.getClass().getName()+"."+method.getName()+" 准备去干一票");
Object result = proxy.invokeSuper(obj, args);
System.out.println("干完这一票 "+obj.getClass().getName()+"."+method.getName());
return result;
}
}
AspectJ 声明式(以上的第二种配置方式)
package test.proxy;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
@Aspect
public class AspectJForBuy {
@Before("execution(* buy*(..))")
public void beforBuything(){
System.out.println("为了-----干了一票");
}
}