静态代理
- 抽象主题
public interface Subject {
void make();
}
- 真正的主题
public class RealSubject implements Subject {
@Override
public void make() {
System.out.println("执行真正的主题");
}
}
- 代理主题
public class ProxySubject implements Subject {
private Subject subject;
public ProxySubject(Subject subject) {
this.subject = subject;
}
@Override
public void make() {
prepare();
this.subject.make();
finish();
}
private void finish() {
System.out.println("主题结束,收尾");
}
private void prepare() {
// 真正的主题开始之前的准备
System.out.println("主题开始前的准备");
}
}
测试:
@Test
public void proxyTest() {
Subject subject = new ProxySubject(new RealSubject());
subject.make();
}
这就是静态代理的实现,静态代理中,一个目标对象对应一个代理对象,代理类在编译时期就已经确定了。
静态代理方式总结
可以做到在不修改目标对象的前提下,拓展目标对象的功能。
缺点是:因为代理对象需要同目标对象实现同样的接口,所以会有很多的代理类,造成类过多;并且,一旦接口中增加方法,目标对象同代理对象都需要进行维护。
解决这个缺点的方式就是使用动态代理
动态代理
- 目标对象接口
public interface IUserDao {
void save(User user);
}
- 目标对象类
public class UserDao implements IUserDao {
@Override
public void save(User user) {
System.out.println("保存数据");
System.out.println(user.toString());
}
}
- 动态代理对象
/**
* 创建动态代理对象
* 动态代理对象不需要实现接口,但是需要指定接口类型
*/
public class ProxyFactory {
//维护一个目标对象
private Object target;
//对象构造时,提供目标对象
public ProxyFactory(Object target) {
this.target = target;
}
public Object getProxyInstance() {
//给目标对象生成代理对象
return Proxy.newProxyInstance(
target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("begin transaction");
Object returnValue = method.invoke(target, args);
System.out.println("Commit Transaction");
return returnValue;
}
}
);
}
}
- 测试
@Test
public void dynaProxy() {
IUserDao userDao = new UserDao();
System.out.println(userDao.getClass());
IUserDao proxyInstance = (IUserDao) new ProxyFactory(userDao).getProxyInstance();
System.out.println(proxyInstance.getClass());
proxyInstance.save(new User("junl",23));
}
从上面的代码可以看出,动态代理对象不需要实现目标对象接口,但是目标对象一定要实现接口,否则不能使用动态代理。
参考