一:什么是代理模式?有什么用?
说白了java当中的代理模式是基于接口,有两个实现类,其中之一负责完成核心的业务逻辑,而另一个代理类则负责实现一些辅助操作,例如:日志,事物等等。
二:传统的代理模式:
interface Food
{
public void eat();
}
class RealFood implements Food
{
@Override
public void eat()
{
System.out.println("老叼吃饭了,吃的很香,但是后来吃出来一条虫子");
}
}
class ProxyFood implements Food
{
private Food food;
public Food bind(Food food)
{
this.food = food;
return this;
}
public void prepare()
{
System.out.println("【吃饭前准备阶段】洗手洗菜烧菜");
}
public void after()
{
System.out.println("【饭后收尾】洗碗洗筷子");
}
@Override
public void eat()
{
prepare();
food.eat();
after();
}
}
public class ProxyDemo
{
public static void main(String[] args)
{
Food food = new ProxyFood().bind(new RealFood());
food.eat();
}
}
输出:
【吃饭前准备阶段】洗手洗菜烧菜
老叼吃饭了,吃的很香,但是后来吃出来一条虫子
【饭后收尾】洗碗洗筷子
但是这种传统的代理模式当业务需求发生更改时,需要变动的地方很多,并不合适真实的开发操作,但是,java提供了动态代理方式,需要代理类实现InvocationHandler接口,看看具体调用(仿真实业务):
package com.proxy.actstatus;
import java.io.Serializable;
@SuppressWarnings("serial")
public class User implements Serializable {
private String name;
private int age;
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setAge(int age) {
this.age = age;
}
public int getAge() {
return age;
}
}
package com.proxy.actstatus;
import java.util.List;
public interface UserDao {
public void doInsert(User u) throws Exception;
public User doUpdate(User u) throws Exception;
public User doDelete(String name) throws Exception;
public User find(String name) throws Exception;
public List<User> findAll() throws Exception;
}
package com.proxy.actstatus;
import java.util.List;
public class UserDaoImpl implements UserDao
{
@Override
public void doInsert(User u) throws Exception {
System.out.println("执行增加方法"+u);
}
@Override
public User doUpdate(User u) throws Exception {
System.out.println("执行更新方法"+u);
return null;
}
@Override
public User doDelete(String name) throws Exception {
System.out.println("执行删除方法"+name);
return null;
}
@Override
public User find(String name) throws Exception {
System.out.println("执行查询方法"+name);
return null;
}
@Override
public List<User> findAll() throws Exception {
System.out.println("执行查询所有方法");
return null;
}
}
package com.proxy.actstatus;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class UserProxy implements InvocationHandler{
private Object target;
public Object bind(Object target) {
this.target = target;
return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
this.log(method.getName());
if(method.getName().matches("do[a-zA-Z0-9]+")) {
this.commit();
}
Object obj = method.invoke(target, args);
return obj;
}
public void log(String methodName) {
System.out.println("LOG:执行了"+methodName);
}
public void commit() {
System.out.println("LOG:执行了事物提交");
}
}
package com.proxy.actstatus;
public class UserProxyTest {
public static void main(String[] args) throws Exception {
UserDao dao = (UserDao) new UserProxy().bind(new UserDaoImpl());
dao.doInsert(new User());
dao.findAll();
}
}
输出:
LOG:执行了doInsert
LOG:执行了事物提交
执行增加方法com.proxy.actstatus.User@238df2e4
LOG:执行了findAll
执行查询所有方法
思考:这种动态代理模式有什么弊端呢?其实无非在于此种代理模式代理对象必须实现了接口,在invoke方法当中,传入了代理对象实现的所有借口,当代理类没有实现任何接口的时候,动态代理就无法使用。
要想不使用接口实现动态代理,可以了解cglib这个包的使用。