設計模式(四) 手動實現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();
    }
}

結果:

 

  

分析總結:

          關注點代碼,就是指重復執行的代碼。

業務代碼與關注點代碼分離,好處?

              -à 關注點代碼寫一次即可;

          -à開發者只需要關注核心業務;

          -à運行時期,執行核心業務代碼時候動態植入關注點代碼; 【代理】

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM