静态代理与动态代理

静态代理:

将一些需要一起协助才能完全任务的操作 放在一个类中,这个类就是静态代理


举一个例子,例如:目标类与事务,需要在save()之前开启事物,在save()之后关闭事物,这个时候就需要一个代理类,将事务与目标类结合起来

	public class PersonDaoProxy implements PersonDao{
		private PersonDao personDao;
		Private Transaction transaction;
		//构造器对类进行实例化
		public PersonDaoProxy(PersonDao personDao, Transaction transaction){
			this.personDao = personDao;
			This.transaction =t ransaction;
		}
		public void savePerson(){
			//将这些操作都交给一个代理来进行操作
			this.transaction.beginTransaction();
			this.personDao.savePerson();
			this.transaction.commit();
		}	
	}
	



这样通过硬编码的方式进行代理就是静态代理,也是静态代理最致命的地方



JDK的动态代理


原理:新建一个拦截器,让新建的拦截器 中的invoke进行代理,然后在客户端生成一个动态代理

例如和上面的例子一样 ,在客户端传入目标类,事务,拦截器就能创建一个代理,这就是JDK的动态代理


JDK的动态代理比静态代理的好处:

1.在也不需要写像上面通过硬编码的方式写的PersonDaoProxy,JDKProxy是在客户端动态生成的,而静态代理是通过硬编码的方法写进去的

2.可以传入多个目标类,因为拦截器中的目标类定义是一个Object,做到了事务的重用,同时拦截器只需要写一次就可以了


JDK的动态代理的不足:
1.在通过构造器新建的拦截器中 public MyIntercetor(Object target, Transaction transaction)目标类和事务通过硬编码参数的的形式传入,如果想添加日志还是要硬编码写进,这样要改代码,很不方便

    2.拦截器中invoke中的if语句if("savePerson".equals(name)),也是硬编码的形式,一旦方法就很多(比如有700个方法),就要判断700次,是很不方便的,如果增加了方法还要在if判断语句中添加多一个


下面是一个例子:是目标类加入事务的例子


新建一个目标类PersonDao和PersonDaoImpl

public interface PersonDao {
	void savePerson();
}

public class PersonDaoImpl implements PersonDao {
	public void savePerson() {
		System.out.println("save Person");
	}
}



新建一个事务(伪代码)

public class Transaction {
  public void init(){
    System.out.println("init----");
  }
  public void destroy(){
    System.out.println("destroy-----");
  }
}


新建一个拦截器

/**
 * 这是一个拦截器
 * 		1.目标类导入进来
 * 		2.事务导入进来
 * 		3.invoke方法
 * 			1).事务的开启
 * 			2).调用目标方法
 * 			3).事务关闭
 * @author Admin
 *
 */
public class MyIntercetor implements InvocationHandler{
	
	private Object target;//这是目标类
	private Transaction transaction;//这是要插进的事务
	
	//构造器注入值
	public MyIntercetor(Object target, Transaction transaction) {
		super();
		this.target = target;
		this.transaction = transaction;
	}


	@Override
	public Object invoke(Object proxy, Method method, Object[] args)
			throws Throwable {
		String name = method.getName();
		if("savePerson".equals(name)){
			this.transaction.init();//开启事务
			method.invoke(target);//这里需要传入一个目标类,目标方法所属的目标类
			this.transaction.destroy();//事务关闭
		}else{
			method.invoke(target);
		}
		return null;
	}

}


测试的方法


	@Test
	public void testJDKProxy(){
		PersonDao target = new PersonDaoImpl();
		Transaction transaction = new Transaction();
		MyIntercetor myIntercetor = new MyIntercetor(target,transaction);
		
		/**
		 * 动态产生一个代理对象
		 * 	三个参数分别是:
		 * 		1.目标类的类加载器
		 * 		2.目标类实现的接口
		 * 		3.拦截器
		 */
		//传入三个参数,就产生了动态代理,可以用目标类接收
		PersonDao personDao1 = (PersonDao)Proxy.newProxyInstance(target.getClass().getClassLoader(),
				target.getClass().getInterfaces(), myIntercetor);
		//这时的目标类不是简单的实体类,而是拥有事务的开启,目标方法的执行,以及事务的关闭功能
		personDao1.savePerson();
	}
	


之后可以输出

init----

save Person

destroy-----




CGLib的动态代理


导入依赖jar

cglib-nodep-2.1_3.jar

 

具体产生的代理类操作(举一个例子,还是目标类和事务的例子)

 

新建PersonDaoImpl(这里不需要接口了,因为CGLib产生代理不是根据目标类所实现的接口来创建的,而是生成目标类的子类为代理对象,与JDKProxyJDKProxy是根据目标类所实现的接口来创建的代理对象)

public class PersonDaoImpl {
	public void savePerson(){
		System.out.println("savePerson");
	}
}

事务Transaction.java

public class Transaction {
	public void beginTransaction(){
		System.out.println("beginTransaction");
	}
	public void commit(){
		System.out.println("commit");
	}
}

创建拦截器MyInterceptor.java

public class MyInterceptor implements MethodInterceptor {

	private Object target;
	private Transaction transaction;
	

	
	public MyInterceptor(Object target, Transaction transaction) {
		super();
		this.target = target;
		this.transaction = transaction;
	}

	//产生代理对象
	public Object createProxy(){
		//代码增强类
		Enhancer enhancer = new Enhancer();
		enhancer.setCallback(this);//参数为拦截器
		enhancer.setSuperclass(target.getClass());//生成代理类的目标类是父类
		return enhancer.create();
	}

	@Override
	public Object intercept(Object arg0, Method method, Object[] arg2,
			MethodProxy arg3) throws Throwable {
		this.transaction.beginTransaction();
		method.invoke(target);
		this.transaction.commit();
		return null;
	}
}


测试单元

@Test
public void testCGLib(){
	Object target = new PersonDaoImpl();
	Transaction transaction = new Transaction();
	MyInterceptor interceptor = new MyInterceptor(target,transaction);
	PersonDaoImpl personDao = (PersonDaoImpl)interceptor.createProxy();//这行代码就是生成了代理类,该代理类的父类是目标类
	personDao.savePerson();
}


输出的结果

beginTransaction
savePerson
commit


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值