• 动态JDK代理方式-实现类增强


    需求描述:

      抽取dao层开启和提交事物交由代理类一并执行

    分析:

      假如UserDao接口中有很多方法,例如addUser()、deleteUser()、updateUser()等等,需要频繁的和数据库打交道,必然在每个方法里都会有开启事物,提交事务的操作。如果把开启事物和提交事物写在一个类A中不同方法中,由一个工厂将dao层和A类进行整合,得到一个代理的UserDao的实现对象,它即有原UserDao实现类中的各个方法,又有A类中的事物方法。即可实现切面管理事物。

    代码:

    UserDao接口:

    package com.xx.dao;
    
    public interface UserDao {
    	//增
    	void addUser();
    	//删
    	void deleteUser();
    	//改
    	void updateUser();
    }
    

     UserDaoImpl实现类:

    package com.xx.dao;
    
    public class UserDaoImpl implements UserDao{
    	@Override
    	public void addUser() {
    		System.out.println("添加用户");
    	}
    	@Override
    	public void deleteUser() {
    		System.out.println("删除用户");
    	}
    	@Override
    	public void updateUser() {
    		System.out.println("更新用户");
    	}
    }
    

     切面类:

    package com.xx.dao;
    
    public class MyAspect {
    	public void before(){
    		System.out.println("开启事物");
    	}
    	public void after(){
    		System.out.println("关闭事物");
    	}
    }
    

     代理工厂类:

    package com.xx.dao;
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    /**
     * 代理工厂(代理UserDao生成特定功能的实现类对象)
     * @author phoebe
     *
     */
    public class ProxyFactory {
    	//被代理类
    	private static UserDao userDao = new UserDaoImpl();
    	//切面类
    	private static MyAspect myAspect =  new MyAspect();
    	/* 获取新的代理类
    	 * loader:类加载器(选当前类的类加载器)
    	 * 		方法一:当前类.class.getClassLoader();
    	 * 		方法二:对象.getClass.getClassLoader();
    	 * interfaces:代理生成的对象是哪个接口的实现类呢?
    	 * 		方法一:new Class[]{接口.class}
    	 * 		方法二:对象.getClass().getInterfaces(),此仅能返回当前对象实现类的接口,并不能返回其父接口
    	 * InvocationHandler:使用其调用处理程序的指定值从子类(通常为动态代理类)构建新的 Proxy 实例。 
    	 */
    	public static UserDao createProxyUserService(){
    		UserDao proxyInstance = (UserDao) Proxy.newProxyInstance(userDao.getClass().getClassLoader(), userDao.getClass().getInterfaces(), new InvocationHandler() {
    			@Override
    			public Object invoke(Object proxy, Method method, Object[] args)
    					throws Throwable {
    				Object object = null;
    				//可以通过method.getName()控制是否增强
    				if(!("updateUser".equals(method.getName()))){
    					myAspect.before();
    					object = method.invoke(userDao, args);
    					myAspect.after();
    					System.out.println(object+"为什么是null?尚未知晓");
    					return object;	
    				}
    				System.out.println(object+"为什么是null?尚未知晓");
    				return object;	
    			}
    		});
    		//返回UserDao的新实例对象
    		return proxyInstance;
    	}
    }
    

     测试类:

    package com.xx.action;
    import com.xx.dao.ProxyFactory;
    import com.xx.dao.UserDao;
    public class TestProxy {
    	public static void main(String[] args) {
    		UserDao userService = ProxyFactory.createUserService();
    		userService.addUser();
    		userService.deleteUser();
    		userService.updateUser();
    	}
    }
    

     效果:

    开启事物
    -------添加用户-------
    关闭事物
    null为什么是null?尚未知晓
    开启事物
    -------删除用户-------
    关闭事物
    null为什么是null?尚未知晓
    null为什么是null?尚未知晓
    
    Best Regards
  • 相关阅读:
    常见优化函数
    排序算法
    小米编程题
    leetcode 刷题
    beam_search 和 viterbi算法的区别
    快速排序
    vitrebi算法进行分词的案例
    python 进行视频剪辑
    keras实现MobileNet
    HMM、CTC、RNN-T训练时所有alignment的寻找方法
  • 原文地址:https://www.cnblogs.com/pecool/p/8261738.html
Copyright © 2020-2023  润新知