spring AOP

AOP: Aspect Oriented Programming 面向切面编程
OOP: Object Oriented Programming 面向对象编程

一、AOP简介

AOP是基于OOP基础之上新的编程思想,OOP面向的主要是对象是类,而AOP面向的主要对象是切面,一般用来进行处理日志、安全管理、事务管理等。AOP是Spring中重要的核心点,ioc容器没有依赖AOP,但是AOP提供了很强大的功能。
简单来说:AOP就是在程序运行期间,在不修改原有代码的情况下,给程序添加额外功能的技术,这种编程方式叫做AOP。

public class UserServiceImpl implements UserService{
    @Override
    public User get(Integer id) {
        System.out.println("查询");
        return new User();
    }
    /*
    	System.out.println("日志");
 		System.out.println("查询");
        return new User();
	*/

    @Override
    public void add(User user) {
        System.out.println("添加");
    }

    @Override
    public void del(Integer id) {
        System.out.println("删除");
    }

    @Override
    public void upt(User user) {
        System.out.println("修改");
    }
}

这个代码非常简单,但是如果需要添加日志输出,同时修改会变得麻烦,这里可以使用代理的方式来实现添加日志。
代理是一种设计模式,AOP底层是通过动态代理来实现的。
1)静态代理
2)动态代理
jdk动态代理:需保证被代理的类实现了接口
cglib动态代理:无需接口
代理类

public class UserHandler implements InvocationHandler {

    // 被代理的对象
    Object target;

    public UserHandler(Object target) {
        this.target = target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Object result = null;
        try {
            LoggUtil.start(method,args);
            //执行目标
            result = method.invoke(target, args);
            LoggUtil.stop(method,args);
        } catch (Exception e) {
            LoggUtil.logException(method,e);
        } finally {
            LoggUtil.end(method);
        }
        return result;
    }
}

测试添加日志

public class Test {

    @org.junit.Test
    public void Test(){
        UserService userService =(UserService) createProxy(new UserServiceImpl());

        userService.get(1);
    }

    public static Object createProxy(Object object){
        ClassLoader classLoader = object.getClass().getClassLoader();
        Class<?>[] classes = object.getClass().getInterfaces();
        InvocationHandler handler = new UserHandler(object);
        // 动态创建代理类
        Object o = Proxy.newProxyInstance(classLoader, classes, handler);
        return o;
    }
}

日志类

public class LoggUtil {

    public static void start(Method method,Object ... objects){
        System.out.println(method.getName()+"方法开始执行,参数是:"+ Arrays.asList(objects));
    }

    public static void  stop(Method method,Object ... objects){
        System.out.println(method.getName()+"方法执行结束,参数是:"+ Arrays.asList(objects));
    }

    public static void logException(Method method,Exception e){
        System.out.println(method.getName()+"方法出现异常:"+ e.getMessage());
    }

    public static void end(Method method){
        System.out.println(method.getName()+"方法执行结束");
    }
}

以上为jdk动态代理的实现,在spring中可以不用编写这样复杂的代码,只需要利用AOP,就可以实现,当然,AOP底层依赖的也是动态代理

AOP术语

  • 切面(Aspect): 指关注点模块化,这个关注点可以横切多个对象
  • 连接点(Join point):在程序执行过程中某个特定的点
  • 通知(Advice):在切面某个特定的连接点上执行的动作
  • 切点(Pointcut):匹配连接点的断言,通知和切点表达式相关联,并在满足这个切点的连接点上运行
  • 引入(Introduction):声明额外的方法或者某个类型的字段
  • 目标对象(Target object):被一个或者多个切面所通知的对象
  • AOP代理(AOP proxy):AOP框架创建的对象,用来实现切面契约(aspect contract)(包括通知方法执行等功能)。
  • 织入(Weaving):把切面连接到其他的应用程序类型或者对象上,并创建一个被通知的对象的过程。

AOP通知类型

  • 前置通知(Before advice):在连接点之前运行但无法阻止执行流程进入连接点的通知。
  • 后置返回通知(After returning advice):连接点正常完成后执行。
  • 后置异常通知(After throwing advice):方法抛出异常时执行
  • 后置通知(After advice):当连接点退出的时候执行的通知(无论是正常返回还是异常退出)。
  • 环绕通知(Around Advice):环绕连接点的通知,最强大的通知类型。可以在方法调用前后完成自定义行为,选择是否继续执行连接点或直接返回自定义的返回值或抛异常结束。

AOP实现

@Component
@Aspect
public class LoggUtil {

    @Before( "execution(* com.lc.User..*.*(..))")
    public static void before(){
        System.out.println("方法前");
    }

    @After("execution(* com.lc.User..*.*(..))")
    public static void after(){
        System.out.println("方法前");
    }

    @AfterThrowing("execution(* com.lc.User..*.*(..))")
    public static void afterException(){
        System.out.println("方法异常");
    }

    @AfterReturning("execution(* com.lc.User..*.*(..))")
    public static void afterRet(){
        System.out.println("方法异常");
    }
}
    @Test
    public void Test02(){
        ClassPathXmlApplicationContext ioc = new ClassPathXmlApplicationContext("classpath:/spring_aop.xml");
        UserService bean = (UserService)ioc.getBean("userServiceImpl");
        UserService be = ioc.getBean(UserService.class);
        bean.get(1);
    }
<?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.lc.User" >
    </context:component-scan>

    <!--开启AOP-->
    <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
</beans>

T:XY

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值