静态代理:

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


举一个例子,例如:目标类与事务,需要在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,JDK的Proxy是在客户端动态生成的,而静态代理是通过硬编码的方法写进去的

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




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

拦截器中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产生代理不是根据目标类所实现的接口来创建的,而是生成目标类的子类为代理对象,与JDKProxy,JDKProxy是根据目标类所实现的接口来创建的代理对象)


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