JavaEE基础02-spring(AOP)

AOP的功能先从一个例子开始。

 加减乘除的一个功能,需要在每个方法开始和结束时打印东西。(就是需求一)

 方法一(非常不推荐):

package com.guigu.spring2;

/**
 * Created by Zhuxiang on 2020/5/18.
 */
public class ArithmeticCalculatorImpl implements ArithmeticCalculator{

    @Override
    public int add(int a, int b) {
        System.out.println("日志开始了:"+a+"加"+b);
        int add=a+b ;
        System.out.println(add);
        return add;
    }

    @Override
    public int sub(int a, int b) {
        System.out.println("日志开始了:"+a+"减"+b);
        int sub=a-b;
        System.out.println(sub);
        return sub ;
    }
}
ArithmeticCalculatorImpl

 方法二:使用静态代理(不推荐)(但是需要复习一下代理的思想)

下图中被代理类是接口的实现类,代理类也需要实现接口,这样才能提供方法。

package com.guigu.spring2;

/**
 * Created by Zhuxiang on 2020/5/18.
 */
public class ArithmeticCalculatorImpl implements ArithmeticCalculator{

    @Override
    public int add(int a, int b) {
        int add=a+b ;
        System.out.println(add);
        return add;
    }

    @Override
    public int sub(int a, int b) {
        int sub=a-b;
        System.out.println(sub);
        return sub ;
    }
}
ArithmeticCalculatorImpl
package com.guigu.spring2;

/**
 * Created by Zhuxiang on 2020/5/18.
 */
public class StaticProxy implements ArithmeticCalculator{
    private ArithmeticCalculator ar;
    public StaticProxy(ArithmeticCalculator ar) {
        this.ar=ar;
    }
    @Override
    public int add(int a, int b) {
        String s="加";
        noQueue(a,b,s);
        int add = ar.add(a, b);
        return add;
    }

    @Override
    public int sub(int a, int b) {
        String s="减";
        noQueue(a,b,s);
        int sub = ar.sub(a, b);
        return sub;
    }
    // 代理类本身自带功能;
    public void noQueue(int a,int b,String s) {
        System.out.println("日志开始了:"+a+s+b);
    }
}
StaticProxy
package com.guigu.spring2;

/**
 * Created by Zhuxiang on 2020/5/18.
 */
public class main {
    public static void main(String[] args) {
        ArithmeticCalculator a2 = new StaticProxy(new ArithmeticCalculatorImpl());
        a2.add(2,1);
        a2.sub(2,1);
    }
}
//日志开始了:2加1
//3
//日志开始了:2减1
//1
main

方法三:使用动态代理(详细内容去java基础反射复习)(可以用,但是和aop比起来麻烦得多)

package com.guigu.spring2;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Arrays;

/**
 * Created by Zhuxiang on 2020/5/18.
 */
public class LoggingProxy {
    //要代理的对象
    private  ArithmeticCalculator target;

    public LoggingProxy(ArithmeticCalculator target) {
        this.target = target;
    }
    public ArithmeticCalculator getLoggingProxy(){
        //代理对象由哪一个类加载器进行加载
        ClassLoader loader=target.getClass().getClassLoader();
        //代理对象的类型,即其中有哪些方法
        Class<?>[] interfaces=new Class[]{ArithmeticCalculator.class};
        //当调用代理对象其中的方法时,会执行的代码
        InvocationHandler h=new InvocationHandler() {
            /**
             * proxy: 正在返回的那个代理对象,一般情况下,invoke方法里不使用(调用里面的方法会导致死循环)
             * method: 正在被调用的方法
             * args: 传入的参数
             */
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                String methodName=method.getName();
                System.out.println("日志:"+methodName+"begins with"+ Arrays.asList(args));
                //执行方法
                Object result = method.invoke(target, args);
                System.out.println("日志:"+methodName+"ends with"+ result);
                return result;
            }
        };
        ArithmeticCalculator proxy = (ArithmeticCalculator) Proxy.newProxyInstance(loader, interfaces, h);
        return proxy;
    }
}
LoggingProxy
public class main {
    public static void main(String[] args) {
        ArithmeticCalculator a1 = new ArithmeticCalculatorImpl();
        ArithmeticCalculator a2 = new LoggingProxy(a1).getLoggingProxy();
        a2.add(2,1);
        a2.sub(2,1);
    }
}
//日志:addbegins with[2, 1]
//3
//日志:addends with3
//日志:subbegins with[2, 1]
//1
//日志:subends with1
main

上面是自己写的,下面是ppt里的。对比着看吧,反正效果一样的,log先忽视掉。

 

 

 

 了解了上面的内容,springAop正式开始。

1,加入jar包

 2,在配置文件中加入aop的命名空间

3,基于注解的方式

①在配置文件中加入

<!--使Aspect注解起作用,自动匹配的类生成代理对象-->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>

②把横切关注点的代码抽象到切面的类中。

  切面首先是一个ioc中的bean,即加入@component 注解

  切面还需要加入@Aspect 注解

③在类中声明各种通知

  声明一个方法

  在方法前加上@......注解,在注解后加上具体的类(具体看下面代码)

④可以在通知方法中声明一个类型为joinpoint的参数。然后就能访问链接细节。如方法名称和参数值

------------------------------具体代码-------------------------------

package com.guigu.spring2aop;

import org.springframework.stereotype.Component;

/**
 * Created by Zhuxiang on 2020/5/18.
 */
@Component
public class ArithmeticCalculatorImpl implements ArithmeticCalculator {

    @Override
    public int add(int a, int b) {
        int add=a+b ;
        System.out.println(add);
        return add;
    }

    @Override
    public int sub(int a, int b) {
        int sub=a-b;
        System.out.println(sub);
        return sub ;
    }
}
ArithmeticCalculatorImpl
package com.guigu.spring2aop;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;

import java.util.Arrays;
import java.util.List;

/**
 * Created by Zhuxiang on 2020/5/18.
 */
//把类声明为切面    1,放入ioc容器 2,声明为切面
@Aspect
@Component
public class LoggingAspect {
    //声明该方法是一个前置
    @Before("execution(public int com.guigu.spring2aop.ArithmeticCalculator.*(int,int))")
    public void beforeMethod(JoinPoint joinPoint){
        String name = joinPoint.getSignature().getName();
        List<Object> args= Arrays.asList(joinPoint.getArgs());
        System.out.println("日志开始了 "+name+" 参数 "+args);
    }
    @After("execution(* com.guigu.spring2aop.*.*(int,int))")
    public void afterMethod(){
        System.out.println("日志结束了");
    }
}
LoggingAspect
package com.guigu.spring2aop;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * Created by Zhuxiang on 2020/5/18.
 */
public class Main {
    public static void main(String[] args) {
        ApplicationContext c = new ClassPathXmlApplicationContext("applicationContext.xml");
        ArithmeticCalculator ari=(ArithmeticCalculator)c.getBean("arithmeticCalculatorImpl");
        ari.add(3,1);
    }
}
main
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd">
    <context:component-scan
            base-package="com.guigu.spring2aop">
    </context:component-scan>
    <!--使Aspect注解起作用,自动匹配的类生成代理对象-->
    <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
</beans>
applicationContext.xml

猜你喜欢

转载自www.cnblogs.com/zhuxiang1029/p/12913416.html