• 设计模式(四) 手动实现AOP代理


    1.事务的使用:

          每次对数据库操作我们都需要开启事务,事务开启后,我们就需要对数据库进行一次或者多次操作,当操作完成后就需要提交事务。比如一个业务中多次操作数据库,但是当某个方法出错的时候,我们需要整体回滚,

    所以我们把业务的操作绑定在一个事务中。)


     2.手动实现aop管理事务

          我们都知道,如果在业务流程代码中增加事务的开启与提交操作,那么我们在一个类中维护的将会是业务与事务的代码。代码少还可以,但是如果代码量很大,维护起来将显得臃肿复杂。那么我们能不能将业务与事务的代码剥离开来,分开进行维护呢?

        答案肯定是可行的。下面我们通过手动实现AOP代理。    

            AOP     面向切面的编程:

                    AOP可以实现“业务代码”与“关注点代码”分离,关注点代码可以想象为事务的那部分代码。

    代码示例:

    IUserDao 接口对象
    package com.murong.aop;
    
    //接口
    public interface IUserDao
    {
        void save();
    }

    UserDao  目标对象

    package com.murong.aop;
    
    import org.springframework.stereotype.Component;
    
    /**
     * 目标对象
     */
    @Component // 加入IOC容器
    public class UserDao implements IUserDao
    {
        @Override
        public void save()
        {
            System.out.println("-----核心业务:保存!!!------");
        }
    }

    Aop  关注点代码类

    package com.murong.aop;
    
    import org.springframework.stereotype.Component;
    
    /**
     * 关注点代码类
     */
    @Component // 加入IOC容器
    public class Aop
    {
        // 重复执行的代码
        public void begin()
        {
            System.out.println("事务开启");
        }
    
        // 重复执行的代码
        public void end()
        {
            System.out.println("事务结束");
        }
    }
    ProxyFactory  代理工厂
    package com.murong.aop;
    
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    
    /**
     * 代理工厂 *
     */
    public class ProxyFactory
    {
        public static Object newProxyInstance(final Object target,final Aop aop)
        {
            // 生成代理对象的方法
            return Proxy.newProxyInstance(
                    target.getClass().getClassLoader(),
                    target.getClass().getInterfaces(),
                    new InvocationHandler()
                    {
    
                        @Override
                        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
                        {
                            aop.begin();// 关注点代码
                            Object result = method.invoke(target, args);// 执行目标对象的方法
                            aop.end();// 关注点代码
                            return result;
                        }
                    });
        }
    }

    applicationContext  spring配置文件

    <?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:p="http://www.springframework.org/schema/p"
           xmlns:context="http://www.springframework.org/schema/context"
           xsi:schemaLocation="
            http://www.springframework.org/schema/beans
            http://www.springframework.org/schema/beans/spring-beans.xsd
            http://www.springframework.org/schema/context
            http://www.springframework.org/schema/context/spring-context.xsd"
           default-autowire="byType">
    
        <!-- 开启注解扫描 -->
        <context:component-scan base-package="com.murong.aop"></context:component-scan>
        <!-- 调用工厂方法,返回UserDao的代理对象 -->
        <bean id="userDao_proxy" class="com.murong.aop.ProxyFactory" factory-method="newProxyInstance">
            <constructor-arg index="0" type="java.lang.Object" ref="userDao"></constructor-arg>
            <constructor-arg index="1" type="com.murong.aop.Aop" ref="aop"></constructor-arg>
        </bean>
    </beans>

    App  测试类

    package com.murong.aop;
    
    import org.junit.Test;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    public class App
    {
        private ApplicationContext ac = new ClassPathXmlApplicationContext("com/murong/aop/applicationContext");
        @Test
        public void test()
        {
            IUserDao dao = (IUserDao) ac.getBean("userDao_proxy");
            dao.save();
        }
    }

    结果:

      

    分析总结:

              关注点代码,就是指重复执行的代码。

    业务代码与关注点代码分离,好处?

                  -à 关注点代码写一次即可;

              -à开发者只需要关注核心业务;

              -à运行时期,执行核心业务代码时候动态植入关注点代码; 【代理】

  • 相关阅读:
    js,timeout,promise执行顺序
    vue数据响应的坑
    css中的block与none
    javascript 私有化属性,和公共属性
    animal与@keyframe
    css3中的translate,transform,transition的区别
    AngularJS实现原理
    bootstrap添加多个模态对话框支持
    ajax
    jQuery点击弹出层,弹出模态框,点击模态框消失
  • 原文地址:https://www.cnblogs.com/yuanchaoyong/p/6416372.html
Copyright © 2020-2023  润新知