spring5之AOP

AOP(概念)
    1.面向切面编程
      把业务逻辑各个部分进行分离,降低耦合度,提高重用性
    2.通俗表述:不修改源代码,在主干功能添加新功能
    3.用登录例子来说明aop
     
AOP(底层原理)
    1.底层使用动态代理
        (1)动态代理有两种情况
            第一种 有接口情况,使用JDK动态代理
                    1.创建接口实现类的代理对象
                    2.在代理对象的方法里增加一些新功能
            第二种 没有接口情况,使用CGLIB动态代理
                    1.创建当前类的子类的代理对象
                    2.子类继承当前类并重写父类的方法,
                    super调用父类方法并增加新功能
                 


   
                    
AOP(JDK动态代理)
    1.使用JDK动态代理,使用Proxy类里的方法创建代理对象                
        (1)调用newProxyInstance方法返回接口代理类的实例    
            方法有三个参数
            第一个参数:类加载器
            第二个参数:增强方法所在的类实现的接口,支持多个接口
            第三个参数:是一个接口InvocationHandler,需要一个类来
            实现这个接口InvocationHandler,创建代理对象,invoke方法里写增强的功能
    2.JDK动态代理代码
        (1)创建接口,定义方法
        (2)创建接口的实现类,实现方法
    3.使用Proxy类创建接口代理对象
        public class JDKProxy {
            public static void main(String[] args) {
                //创建接口实现类的代理对象
                Class[] interfaces = {UserDao.class};
                UserDaoImpl userDao = new UserDaoImpl();
                //用接口等于实现类创建代理对象
                UserDao dao =(UserDao) Proxy.newProxyInstance(JDKProxy.class.getClassLoader(), interfaces, new UserDaoProxy(userDao));
                int result =  dao.add(1, 2);
                System.out.println("result"+result);
           }

       }
        
        //创建代理对象代码
        class UserDaoProxy implements InvocationHandler {

            //把需要增强的方法所在的类的对象传递过来(被代理对象)
            //通过有参构造传递
            private Object obj;
            public UserDaoProxy(Object obj) {
                this.obj = obj;
            }

            //增强的逻辑代码
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                //方法之前的增加处理
                System.out.println("方法之前执行"+method.getName()+":传递的参数.."+ Arrays.toString(args));

                //被增加的方法的执行
                Object res = method.invoke(obj, args);

                //方法之后的增加处理
                System.out.println("方法之后输出"+obj);
                return res;
            }
        }



AOP(术语)
    1.连接点
        类里面的哪些方法可以被增强(增加功能),这些方法都被称为连接点
    2.切入点
        实际被增强的方法叫做切入点
    3.通知(增强)
        (1)实际增强的逻辑部分称为通知
        (2)有多种类型
            *前置通知
            *后置通知
            *环绕通知
            *异常通知
            *最终通知
    4.切面
        把通知应用到切入点的过程称为切面
        



AOP操作(准备)
    1.Spring框架一般都是基于AspectJ实现AOP操作
        (1)AspectJ是一个独立的AOP框架,通常和Spring一起使用
    2.基于AspectJ实现AOP操作
        (1)基于xml配置文件
        (2)基于注解方式(实际中使用)

    3.项目引入AOP依赖
    4.切入点表达式
        (1)作用是对哪个方法进行增强
        (2)语法(权限修饰符是public/private):
            execution([权限修饰符][返回类型][类的全路径][方法名称]([参数列表]))
            
            例一:对com.xlj.dao.BookDao类里面的add方法进行增强
            //*表示任一,返回类型可以省略,..表示参数列表
                execution(* com.xlj.dao.BookDao.add(..))
        
            例二:对com.xlj.dao.BookDao类里面的所有方法(*表示)进行增强
                execution(* com.xlj.dao.BookDao.*(..))
        
            例二:对com.xlj.dao.包里的所有类(*表示),类里面的所有方法(*表示)进行增强
                execution(* com.xlj.dao.*.*(..))
      


 
AOP操作(基于注解方式进行aop操作)    
    1.创建类,定义方法
    2.创建增强类(里面写增强的部分)
        (1)在里面写不同的方法表示不同的通知类型
    3.进行通知的配置
        (1)写配置文件开启注解扫描(配置类也可以实现)
            引入context的名称空间
            <context:component-scan base-package="com.xlj.spring5.aopanno"></context:component-scan>
        (2)使用注解创建被增强类和增强类的对象
        (3)在增强类上加注解@Aspect
        (4)在spring配置文件中开启生成代理对象
            引入aop的名称空间
            <!--   开启AspectJ生成代理对象 ,有@Aspect的注解的类就生成代理对象-->
            <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
        
    4.配置不同类型的通知
        (1)在增强类的方法上添加它所表示的通知类型注解,并使用切入点表达式
            @Component
            @Aspect
            public class UserProxy {
                //前置通知(value=“切入点表达式”)value可以省略
                @Before("execution(* com.xlj.spring5.aopanno.User.add(..))")
                public  void  before() {
                    System.out.println("before....");
                }
                //最终通知,无论是否发生异常都会执行
                @After("execution(* com.xlj.spring5.aopanno.User.add(..))")
                public  void  after() {
                    System.out.println("after....");
                }
                //后置通知,有返回结果才执行,有异常不执行
                @AfterReturning("execution(* com.xlj.spring5.aopanno.User.add(..))")
                public  void  afterReturning() {
                    System.out.println("afterReturning....");
                }
                //异常通知,在增强的方法出现异常时才会执行
                @AfterThrowing("execution(* com.xlj.spring5.aopanno.User.add(..))")
                public  void  afterThrowing() {
                    System.out.println("afterThrowing....");
                }
                //环绕通知
                @Around("execution(* com.xlj.spring5.aopanno.User.add(..))")
                public  void  around(ProceedingJoinPoint proceedingJoinPoint)throws Throwable {
                    System.out.println("环绕之前...");
                    //执行被增强的方法
                    proceedingJoinPoint.proceed();
                    System.out.println("环绕之后....");

                }
            }

    5.相同的切入点的抽取(就是重复写的execution)    
        (1)//相同切入点的抽取
            @Pointcut(value = "execution(* com.xlj.spring5.aopanno.User.add(..))")
            public  void  pointdemo() {

            }
        (2)通知注解的表达式改为value=“方法名()”
            例如@Before(value = "pointdemo()")
        
    6.多个增强类对同一个方法增强,设置增强类的优先级
        (1)在增强类上添加注解@Order(数字类型值),数字越小优先级越高
                @Order(1)
    
    7.完全注解开发
    (1)写配置类
        //表示作为配置类
        @Configuration
        //开启注解扫描
        @ComponentScan(basePackages = {"com.xlj"})
        //开启Aspect生成代理对象
        @EnableAspectJAutoProxy(proxyTargetClass = true)
        public class ConfigAop {
        }
    (2)编写测试方法(和加载bean不太一样)
        //加载配置类
        ApplicationContext context =
            new AnnotationConfigApplicationContext(ConfigAop.class);

        



AOP操作(基于xml配置文件进行aop操作)        
    1.创建增强类和被增强类以及各自方法
    2.在xml配置文件创建两个类的对象
    3.在xml配置文件中配置切入点
        <!--  配置aop增强-->
            <aop:config>
        <!--  配置切入点-->
                <aop:pointcut id="p" expression="execution(* com.xlj.spring5.aopxml.Book.buy(..))"/>
        <!--   配置切面-->
                <aop:aspect ref="bookProxy">
        <!--配置把通知应用到切入点,method="before"通知,pointcut-ref="p"切入点-->
                    <aop:before method="before" pointcut-ref="p"></aop:before>
                </aop:aspect>
            </aop:config>

            

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值