AOP 面向切面编程 解析

Spring AOP 基本概念:

1.连接点(JoinPoint):类中的所有方法;

2.切入点(Pointcut):缺失共性功能代码的方法;

3.通知(Advice):被抽取的共性功能的代码殴,通知有位置之分,也就是从切入点方法中被抽取代码的前面还是后面抽取出来的代码,叫通知类型。通知类型有:前置通知和后置通知。

4.引入(Introduction):通知只能抽取逻辑代码,变量是拿不出来的,只能把变量引入到切入点方法中去。

5.目标对象(TargetObject):有切入点方法的对象。

6.AOP代理(AOP Proxy):spring代理目标对象就叫做AOP代理。

7.织入(Weaving):代理对象把通知织入到目标对象的切入点方法中个,是一个动作。

8.切面(Aspect):通知和切入点之间的关系。

AOP的核心就是代理模式,Spring AOP的实现对于接口来说就是使用的JDK的动态代理来实现的,而对于类的代理使用CGLIB来实现。

JDK的动态代理相关代码如下:

interface UserDao {
    public void targetObject();
}

class UserDaoImpl implements UserDao {
    public void targetObject(){
        System.out.println("this is targetObject");
    }
}

//import java.lang.reflect.InvocationHandler;
//import java.lang.reflect.Method;

class MyInvocationHandler implements InvocationHandler {

    /*
    *  1.把目标对象传进来
    *  2.定义目标对象
    * */
    Object obj;
    public MyInvocationHandler(Object obj){
        this.obj = obj;
    };
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println(new Date+"加入前置通知 before");
           
        //调用需要增强功能的 目标对象,需要得到类obj 及 参数类型及个数args         
        Object object = method.invoke(obj,args);

        System.out.println(new Date+"加入前置通知 after");
        return object;
    }
}

class Main{
    public static void main(String[] args) {
        UserDao userDao = new UserDaoImpl();
        //jdk的动态代理来实现代理上面的对象,并对它里面的targetObject方法进行功能从增加。
        //其中需要jdk中的reflect.Proxy对象中的方法
        //newProxyInstance 方法的三个参数是什么意思?
        /*
        * 1.loader:类加载器,类的字节码对象获得,写法也是固定的
        * 2.interfaces:得到该对象的所有实现接口的字节码对象的数组
        * 3.需要一个实现了InvocationHandler接口的对象,这步需要自己自己动手实现,对目标对象功能                
        *   的增强就是在这个对象
        * 中完成的。
        * */
        InvocationHandler h =  new MyInvocationHandler(userDao) ;

        //获得代理对象,该对象将 我们需要增强的要代理的方法进行增强,可以说,这个代理就是"增                  
        //强"方法和目标方法进行融合后得到的对象
        Object newProxyInstance = Proxy.newProxyInstance(userDao.getClass().getClassLoader(),userDao.getClass().getInterfaces(),h);
        //执行代理对象增强后的方法
        UserDao userDao1 = (UserDao) newProxyInstance;
        userDao1.targetObject();
    }
}

cglib动态代理:

class Student {
    public void study(){
        System.out.println("study!");
    };
}

class CallBackMethod implements MethodInterceptor {

    /*
    * proxy:代理对象
    * method:目标对象中的方法
    * args:木匾对象方法参数
    * methodProxy:代理对象中的代理方法对象
    *
    * */
    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println("hahahahaha");
        Object o1 = methodProxy.invokeSuper(o,objects);
        System.out.println("hehehehehe");
        return o1;
    }
}

 class Test {
    /*
    * cglib动态代理的实现步骤
    * 1.生成(空的)字节码对象Enhancer
    * 2.设定这个字节码对象的父类(目标对象)
    * 3.设置被增强的方法、回调函数、拦截方法
    * 4.得到代理对象
    *
    * */
    public static void main(String[] args) {
        Enhancer enhancer = new Enhancer();

        enhancer.setSuperclass(Student.class);

        Callback callback = new CallBackMethod();
        enhancer.setCallback(callback);
        //得到代理对象(用代理类创建代理对象)
        Student student = (Student) enhancer.create();
        student.study();
    }
}

AOP通知的类型:before、after、afterReturning 、afterThrowing 、around

AOP通知类型的执行顺序,通知类型分为两种:前置通知  与   后置通知。

前置通知:before、around

后置通知:after、afterReturning、around

      对于前置通知来说,它的执行顺序与配置文件(spring.xml)中的配置顺序一致。

      对于后置通知来说,它的执行顺序与配置文件中的配置顺序相反,最后的后置通知先执行。

AOP通知获取匹配方法的参数

AOP通知在进行匹配切入点的方法的时候,可以吧切入点方法的参数给获取到。

1.通过给通知添加JoinPorintde 形参来获得被匹配方法的参数,改参数位于形参的第一位,使用对应的Joinpoint 的 getArgs()

来获得对应的取值。

2.AOP通知还可以使用切入点表达式指定通知参数,参数的名称为通知中用于获取参数值得参数名称。

注意:上诉格式中变量名分别定义在配置文件与类中,如果修改一方,另一方不修改,就会出现错误。

 

在使用Spring AOP注解时,需要在配置文件

   <!--开启aop注解-->
    <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
<aop:config>
<aop:pointcut id="poc" expression="execution(* *..*.method1(int,String))"/>
        <aop:aspect ref="advice">
            <aop:around method="around" pointcut-ref="poc"></aop:around>
        </aop:aspect>
</aop:config>

espression: 切点表达式,就是需要增强功能的方法(需要全路径 包括返回值类型

原型: public void com.aop.ClassName.methodName(args1_Type,args2_Type))

aspect ref:使用哪种通知方式去使用我们的(增强方法),方式就是5种通知类型,method:通知类中的具体方法名。

pointcut-ref:增强功能的目标对象的引用 id

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值