动态代理,可以理解为在不修改源码的情况下,对指定的方法进行增强。
JDK Proxy实现动态代理:被增强的类需要实现接口
public interface IUserDao {
public void save();
public void update();
public void find();
public void delete();
}
public class UserDaoImpl implements IUserDao {
public void save() {
System.out.println("save方法执行");
}
public void update() {
System.out.println("update方法执行");
}
public void find() {
System.out.println("find方法执行");
}
public void delete() {
System.out.println("delete方法执行");
}
}
public class UserDaoProxy implements InvocationHandler{
//需要传入要被增强的对象
private IUserDao dao;
public UserDaoProxy(IUserDao dao){
this.dao = dao;
}
public IUserDao createProxy(){
/*
* this:Proxy.newProxyInstance需要传入一个实现InvocationHandler的类
* 本例中UserDaoProxy implements InvocationHandler 所以直接传入this
*/
return (IUserDao) Proxy.newProxyInstance(UserDaoProxy.class.getClassLoader(), dao.getClass().getInterfaces(),
this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if(method.getName().equals("save")){
System.out.println("执行权限操作检验");
Object obj = method.invoke(dao, args);
return obj;
}
return method.invoke(dao, args);
}
}
public class Demo4 {
@Test
public void test1(){
IUserDao dao2 = new UserDaoImpl();
UserDaoProxy proxy = new UserDaoProxy(dao2);
IUserDao dao = proxy.createProxy();
dao.save();
dao.find();
dao.update();
dao.delete();
}
}
执行Demo4:
CGLIB实现动态代理:被增强的类不需要实现任何接口
public class CustomerDao {
public void save(){
System.out.println("Customer save 方法执行");
}
public void update(){
System.out.println("Customer update 方法执行");
}
}
public class CglibProxyFactory implements MethodInterceptor {
/*
* 不需要传入要被增强的对象
*/
public CustomerDao createProxy(){
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(CustomerDao.class);
enhancer.setCallback(this);//其实就是传入 MethodInterceptor接口,底层回调 intercept方法
Object obj = enhancer.create();
return (CustomerDao)obj;
}
/*
@param proxy "this", the enhanced object
@param method intercepted Method
@param args argument array; primitive types are wrapped
@param methodProxy used to invoke super (non-intercepted method); may be called
*/
@Override
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
if(method.getName().equals("update")){
/*
* 写成 method.invoke(proxy, args) 会报错
*/
Object invoke = methodProxy.invokeSuper(proxy, args);
System.out.println("执行日志记录");
return invoke;
}
return methodProxy.invokeSuper(proxy, args);
}
}
public class Demo5 {
@Test
public void test1(){
CglibProxyFactory fac = new CglibProxyFactory();
CustomerDao proxy = fac.createProxy();
proxy.save();
proxy.update();
}
}
执行Demo5: