提到Java动态代理,必须首先说一下Java静态代理,也就是通常所说的代理模式:
package com.sean;
public class User {
public Integer id;
public String name;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
package com.sean;
public interface UserDAO {
public boolean add(User user);
public boolean delete(Integer id);
public boolean modify(User user);
public Object query(Integer id);
}
package com.sean;
public class UserDAOImpl implements UserDAO {
@Override
public boolean add(User user) {
System.out.println("Add a new user");
return true;
}
@Override
public boolean delete(Integer id) {
System.out.println("Delete a new user");
return true;
}
@Override
public boolean modify(User user) {
System.out.println("Modify a new user");
return true;
}
@Override
public Object query(Integer id) {
System.out.println("Query a new user");
return new User();
}
}
UserDAOImpl类的代理类
package com.sean;
public class UserDAOProxy implements UserDAO {
private UserDAO userDAO;
public UserDAOProxy(UserDAO userDAO){
this.userDAO = userDAO;
}
@Override
public boolean add(User user) {
this.beginTransaction();
boolean result = userDAO.add(user);
this.endTransaction();
return result;
}
@Override
public boolean delete(Integer id) {
this.beginTransaction();
boolean result = userDAO.delete(id);
this.endTransaction();
return result;
}
@Override
public boolean modify(User user) {
this.beginTransaction();
boolean result = userDAO.modify(user);
this.endTransaction();
return result;
}
@Override
public Object query(Integer id) {
this.beginTransaction();
Object obj = userDAO.query(id);
this.endTransaction();
return obj;
}
private void beginTransaction(){
System.out.println("Begin transaction");
}
private void endTransaction(){
System.out.println("End transaction");
}
}
从上面的代码中我们可以发现静态代理一个很明显的问题就是重复代码太多,不利于维护
当然如果想要使用动态代理,目标类必须是一个接口实现类,由于UserDAOImpl是一个接口实现类,满足使用Java动态代理的条件,我们可以使用Java动态代理避免出现太多重复性代码的问题
对于非接口实现类,CGlib可以作为动态代理一个很好的补充
看到这里是不是想到了Spring AOP的应用场景?没错,Spring AOP也是使用Java动态代理实现的(针对非接口实现类,Spring AOP使用CGlib实现)
package com.sean;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class TransactionHandler implements InvocationHandler {
private UserDAO userDAO;
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
this.beginTransaction();
Object obj = method.invoke(userDAO, args);
this.endTransaction();
return obj;
}
public UserDAO createProxy(UserDAO userDAO){
this.userDAO = userDAO;
return (UserDAO)Proxy.newProxyInstance(userDAO.getClass().getClassLoader(),
userDAO.getClass().getInterfaces(), this);
}
private void beginTransaction(){
System.out.println("Begin transaction");
}
private void endTransaction(){
System.out.println("End transaction");
}
}
package com.sean;
public class Test {
public static void main(String[] args) {
UserDAO userDAO = new UserDAOImpl();
TransactionHandler th = new TransactionHandler();
UserDAO userDAOProxy = th.createProxy(userDAO);
userDAOProxy.add(new User());
}
}
UserDAO的代理类及其实例是在运行期间由Proxy的newProxyInstance动态生成的,所以被称为动态代理
从代码中可以看到,动态代理不但快捷方便而且对原代码没有任何侵入性