JavaWeb_(Spring框架)认识Spring中的aop

 

 

1、aop思想介绍(面向切面编程):将纵向重复代码,横向抽取解决,简称:横切

  

 

 

2、Spring中的aop:无需我们自己写动态代理的代码,spring可以将容器中管理对象生成动态代理对象,前提是我们对他进行一些设置;

 

3、Spring-aop是基于动态代理的 – 优先选用JDKProxy动态代理;

  a)Proxy动态代理:被代理的对象必须要实现接口;

  b)Cglib动态代理:被代理的对象不能被final修饰,基于继承;

 

package com.Gary.service;

public interface UserService {

    //
    void save();
    
    //
    void delete();
    
    //
    void update();
    
    //
    void find();
    
}
UserService.java

 

package com.Gary.service;

public class UserServiceImpl implements UserService{

    @Override
    public void save() {
        System.out.println("save()");
    }

    @Override
    public void delete() {
        System.out.println("delete()");
    }

    @Override
    public void update() {
        System.out.println("update()");
    }

    @Override
    public void find() {
        System.out.println("find()");
    }

}
UserServiceImpl.java

 

package com.Gary.test;


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

import com.Gary.service.UserService;
import com.Gary.service.UserServiceImpl;

//UserService代理类
public class UserServiceProxy {
    //代理对象  UserServiceProxy
    //被代理对象  UserService
    public UserService getUserServiceProxy(UserService us) {
        return (UserService) Proxy.newProxyInstance(UserServiceProxy.class.getClassLoader(), 
                               UserServiceImpl.class.getInterfaces(),
                               new InvocationHandler(){
                                    @Override
                                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                                        //增强代码
                                        System.out.println("开启事务");
                                        //需要调用原始的方法
                                        Object invoke = method.invoke(us, args);
                                        System.out.println("提交/回滚");
                                        
                                        return invoke;
                                    }
                                });
    
    }
    
}
UserServiceProxy.java

 

package com.Gary.test;

import org.junit.Test;

import com.Gary.service.UserService;
import com.Gary.service.UserServiceImpl;

public class AopTest {

    @Test
    public void Test1() {
        UserServiceProxy usProxy = new UserServiceProxy();
        UserService us = new UserServiceImpl();
        UserService us_PowerUp = usProxy.getUserServiceProxy(us);
        
        us_PowerUp.find();
        
    }
    
}
AopTest.java

 

4、Spring aop相关名词说明

  代理写小学生暑假作业,3年级以下

  目标对象:UserService(小学生作业)

  被代理对象:被UserServiceProxy增强后的UserService(用你的知识去写的作业)

  JoinPoint、连接点、目标对象中,哪些方法会被拦截;save,delete,update,find (所有要写的作业:数学、语文、英语、王者荣耀代上王者)

    Pointcut切入点:筛选连接点,你最终要增强的方法;save,update,delete (小学生只让你给写数学语文英语,王者荣耀他自己上王者)

    Advice通知/增强:要执行的增强代码 (你用你N年积攒的知识去完成小学暑假作业)

    Introduction介入/引入:在执行时期动态加入一些方法或行为  

    Aspect切面:通知 + 切入点,通知应用到哪个切点

    target目标:被代理对象 (小学生的作业)

    weaving织入:把切面的代码应用到目标对象来创建新的代理对象的过程 (将你的脑子应用到写小学生的暑假作业上)

    proxy代理:把切面的代码应用到目标对象来创建新的代理对象(利用你的知识去完成作业)

 

5、Spring aop配置:

  a)导包:

    i.基本包;

    ii.spring-aspects和spring-aop ;

    iii.aop联盟包 – aopalliance;

    iv.aop织入包 - aspectj.weaver;

  

 

  b)自定义通知,五种自定义通知类型:

    i.before 前置通知

    ii.after 最终通知(后置通知)

    iii.afterReturning 成功通知(后置通知)

    iv.afterThrowing 异常通知(后置通知)

    v.around 环绕通知

    在aop层创建一个MyAdvice.java自定义通知类

package com.Gary.aop;

import org.aspectj.lang.ProceedingJoinPoint;

//自定义通知类
public class MyAdvice {

    //before 前置通知  在目标方法前调用
    public void before() {
        System.out.println("before()");
    }
    
    //after 最终通知(后置通知)在目标方法后调用,无论是否出现异常都会执行 finally
    public void after() {
        System.out.println("after()");
    }
    
    //afterReturning 成功通知(后置通知)    在目标方法执行后,并执行成功,如果方法出现异常,则不会调用
    public void afterReturning(){
        System.out.println("afterReturning()");
    }
    
    //afterThrowing 异常通知(后置通知)   在目标方法执行出现异常的时候才会调用
    public void afterThrowing() {
        System.out.println("after()");
    }
    
    //around 环绕通知  需要我们手动调用目标方法,并且可以设置通知
    public Object around(ProceedingJoinPoint pjp) throws Throwable {
        
        System.out.println("around before");
        Object proceed = pjp.proceed();
        System.out.println("around after");
        return proceed;
    }
    
}
MyAdvice.java

 

  c)配置applicationContext.xml:

<?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:aop="http://www.springframework.org/schema/aop"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd">
        
        <!-- 目标对象 -->
        <bean name="userService" class="com.Gary.service.UserServiceImpl"></bean>
        
        <!-- 通知对象 -->
        <bean name="myAdvice" class="com.Gary.aop.MyAdvice"></bean>
        
        <aop:config>
            <!-- 切入点  expression 切入点表达式 可以配置要增强的方法
                                public void com.Gary.service.UserServiceImpl.save()
                                * com.Gary.service.*ServiceImpl.*(..)
                               id 就是唯一标识
            -->
            <aop:pointcut expression="execution(* com.Gary.service.*ServiceImplabc.*(..))" id="servicePc"/>
            
            <!-- 切面 通知+切入点 -->
            <aop:aspect ref="myAdvice">
                <!-- 通知类型 -->
                <aop:before method="before" pointcut-ref="servicePc"/>
                <!-- 最终通知 后置通知 -->
                <aop:after method="after" pointcut-ref="servicePc"/>
                <!-- 成功通知 后置通知 -->
                <aop:after-returning method="afterReturning" pointcut-ref="servicePc"/>
                <!-- 异常通知 后置通知 -->
                <aop:after-throwing method="afterThrowing" pointcut-ref="servicePc"/>
                <!-- 环绕通知 -->
                <aop:around method="around" pointcut-ref="servicePc"/>
            </aop:aspect>
        </aop:config>
        
</beans>
applicationContext.xml

 

 

 

 

posted @ 2019-12-08 15:40  Cynical丶Gary  阅读(252)  评论(0编辑  收藏  举报