代理对象的作用:
没有代理之前: 在原有的代码上进行事务增强!
有了代理之后: 不动原有的代码 , 把方法进行了事务的增强.
例: 中介(代理)
没有中介之前: 房东自己租房子 , 自己找客源.
有了中介之后: 房东啥都不用管了 , 中介就把房子租好了.
一、JDK代理(对接口的代理)
如果目标对象是接口 , 使用JDK代理! (JDK官方提供)
创建JDK代理对象的要求:被>代理类最少实现一个接口</font,如果没有则不能使用
示例如下:
接口: ProductDao.java
/**
* 一个接口 , 用于JDK代理.
*/
public interface ProductDao {
public void add();
public void del();
public void edit();
public void find();
}
接口的实现类: ProductDaoImpl.java
public class ProductDaoImpl implements ProductDao {
@Override
public void add() {
System.out.println("1.添加商品");
}
@Override
public void del() {
System.out.println("2.删除商品");
}
@Override
public void edit() {
System.out.println("3.修改商品");
}
@Override
public void find() {
System.out.println("4.查询商品");
}
}
增强类: LogAdvice.java
/**
* 日志增强类:
* advice 通知 , 增强代码!
*/
public class LogAdvice {
public static void printLog(String className,String methodName){
System.out.println(new Date().toLocaleString()+" : 记录日志 " + className + "类" + methodName+ "方法执行了... ...");
}
}
测试类: 对目标代码进行增强.
public class JDKAdviceTest {
/**
* 2. 使用JDK代理 , 给dao中的添加和修改方法 进行增加日志类.
*/
@Test
public void demo03() {
// 1.引用目标类.
ProductDao productDao = new ProductDaoImpl();
// 2.对原有类进行增强.
ProductDao proxy = (ProductDao) Proxy.newProxyInstance(
productDao.getClass().getClassLoader(),
productDao.getClass().getInterfaces(),
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
String className = method.getDeclaringClass().getName();
String methodName = method.getName();
// 对方法名进行判断 , 对需要增强的方法进行增强.
if ("add".equals(methodName) || "edit".equals(methodName)) {
// 调用增强类.
LogAdvice.printLog(className, methodName);
}
// 执行目标类方法.
Object invoke = method.invoke(productDao, args);
return invoke;
}
}
);
// 执行方法.
proxy.add();
proxy.del();
proxy.edit();
proxy.find();
}
}
二、CGLIB代理(对类的代理)
创建代理对象的要求: 被代理类不能是最终类,即用final修饰的类不能创建代理对象。
目标类:ProductDao02.java
/**
* 添加一个类 , 用于cglib代理.
*/
public class ProductDao02 {
public void add() {
System.out.println("5.增加用户");
}
public void del() {
System.out.println("6.删除用户");
}
public void edit() {
System.out.println("7.修改用户");
}
public void find() {
System.out.println("8.查询用户");
}
}
增强类: (同上)
测试类: ( 对方法进行增强 )
/**
* 使用cglib代理类 , 给Product02类增加日志(增强)
*/
public class CglibAdviceTest {
@Test
public void test01(){
// 1.引入目标类.
ProductDao02 userDao = new ProductDao02();
// 2.对目标类进行增强. 建立关系.
ProductDao02 cglib = (ProductDao02) Enhancer.create(
userDao.getClass(),
new MethodInterceptor() {
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
String methodName = method.getName();
String className = method.getDeclaringClass().getName();
// 对添加和修改方法进行增强.
if ("add".equals(methodName) || "edit".equals(methodName)) {
// 进行增强 ( 添加日志 )
LogAdvice.printLog(className, methodName);
}
// 执行目标类方法.
Object invoke = method.invoke(userDao, objects);
return invoke;
}
}
);
cglib.add();
cglib.edit();
cglib.del();
cglib.find();
}
}
Spring正式引入代理的特点:
如果是对接口代理使用JDK代理;
如果对类代理使用Cglib代理。