论坛首页 Java企业应用论坛

动态代理

浏览 2065 次
锁定老帖子 主题:动态代理
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2009-02-04   最后修改:2009-05-05
已知接口UserManager.java含有四个方法
package com.bjsxt.spring;
public interface UserManager {

	 public void addUser(String name, String password);
	 
	 public void delUser(int id);
	 
	 public void modifyUser(int id, String name, String password);
	 
	 public String findUserById(int id);
}

类:UserManagerImpl.java实现了以上接口的方法:
package com.bjsxt.spring;
public class UserManagerImpl implements UserManager {

	public void addUser(String name, String password) {
		//checkSecurity();
		System.out.println("UserManagerImpl.addUser()");
	}

	public void delUser(int id) {
		//checkSecurity();
		System.out.println("UserManagerImpl.delUser()");
	}

	public String findUserById(int id) {
		//checkSecurity();
		System.out.println("UserManagerImpl.findUserById()");
		return null;
	}

	public void modifyUser(int id, String name, String password) {
		//checkSecurity();
		System.out.println("UserManagerImpl.modifyUser()");
	}
	
//	private void checkSecurity() {
//		System.out.println("-----checkSecurity-------");
//	}
}

现在有需求要在实现类中的每个方法执行前要添加一段代码,完成完全性检查的功能
最简单的做法我们可以在实现类中添加一个方法如下:

public void checkSecurity(){   
        System.out.println("=====checkSecurity()======");   
 }  

分析以上做法,向实现类中添加方法,破坏了实现类UserManagerImpl.java的封闭性。
假如,随后需求在实现类的每个方法中添加新功能,这样。。。。得不停的改动实现类。。。。。我们的解决办法是,利用代理模式:  
可以使用费静态代理也可使用动态代理;但是静态代理还是要在代理类中的每个方法中添加那个安全性检查方法:
那我们可以不可以不再代理类的每个方法中添加一份需求中新增的方法调用呢?答案是可以,动态代理即可动态的切入我们的实现类中,动态的添加需求的方法,这里我们使用JDK动态代理

JDK动态代理类:代理类必须实现接口java.lang.reflect.InvocationHandler.java

package com.wlh;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class SecurityHandler implements InvocationHandler {

	private Object targetObject;
	public Object proxyObjec;
	
	//构造方法得到代理对象proxyObjec,并且接收目标对象targetObject
	public SecurityHandler (UserManager targetObject){
		  this.targetObject=targetObject;
		  this.proxyObjec
=(UserManager)Proxy.newProxyInstance( 
targetObject.getClass().getClassLoader(),
targetObject.getClass().getInterfaces(),
this);
	}	
	//得到目标对象
	public Object getTargetObject(){
		return this.targetObject;
	}
	
	//得到代理对象
	public Object getProxyObject(){
		return this.proxyObjec;
	}
	
	//动态代理对象执行接口中定义每个方法都将触发该方法
	public Object invoke(Object object, Method method, Object[] args)
			throws Throwable {
		Object result=null;
		 checkSecurity();
		try{
			result=method.invoke(this.targetObject, args);
		}catch(Exception e){
			e.printStackTrace();
		}
		return result;
	}
	//要切入的方法
	public void checkSecurity(){   
        System.out.println("=====checkSecurity()======");   
     }  

}



访问客户端:

package client;
import com.wlh.SecurityHandler;
import com.wlh.UserManager;
import com.wlh.UserManagerImpl;


public class Client {
	
public static void main(String []args){
	
	SecurityHandler securityHandler=new SecurityHandler(new UserManagerImpl());
	 UserManager userManager =(UserManager) securityHandler.getProxyObject();//返回代理类的实例
	 //userManager.addUser("wlh", "wlh");
     // userManager.delUser(3);
	 userManager.findUser(4);
	
}
	
}


DRP采用JDK动态代理为FlowCardManager接口添加事务管理
   一个业务逻辑类ManagerImpl的方法A中可能要包含DAO层类DaoImpl中多个的方法B,C,...的调用;
   在业务逻辑类ManagerImpl上通过JDK动态代理添加事务,动态代理的职能如下:
    a. 假如在指定的add*,delete*,modify*,方法执行前打开连接;
    b. 将事务的自动提交设置为false;
    c. 业务逻辑方法执行(其中多次调用DAO层的方法B,C,....,)
    多次调用DAO层的方法B,C,....,其中得注意2点:
    1.我们使用的ConnectionManager.getConnection();得到的是一个放入ThreadLocal的连接,也就是同一线程共同使用的一个连接,
       因为在A方法中调用方法B,C...所以B,C得到的数据库连接都是同一个连接
    2.Dao方法B,C...的执行只是执行SQL语句,并没有提交事务,也没有关闭连接...以及失败的回滚等,这些操作都由A方法执行完毕后,由动态代理来做;
    e. 出错的情况下,让事务回滚;
    f. 最后关闭连接;
    如果想理解上面的这些话,请这么做:
    1.在ConnectionManager.java 的方法public static Connection getConnection() 中的下面一句上设断点
         Connection conn = (Connection)connectionHolder.get();
    2.启动web服务;
    3.点击分销商库存管理中的流向单维护,会执行业务逻辑方法findAllFlowCard,
         其中包括2个DAO层方法的调用findAllFlowCard和addFlowCardDetail
    4.F6--可一观察到动态代理和业务逻辑方法和dao层方法的执行流程,以及ThreadLocal的Connection的创建次数(就一次)
-------------------------------------
或者参考DRP:记录日志的操作
ItemDao4MySqlFactory.java
LogHandler.java


   

论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics