代理模式就是多一个代理类出来,替原对象进行一些操作,比如我们在租房子的时候回去找中介,为什么呢?
因为你对该地区房屋的信息掌握的不够全面,希望找一个更熟悉的人去帮你做,此处的代理就是这个意思。
再如我们有的时候打官司,我们需要请律师,因为律师在法律方面有专长,可以替我们进行操作,表达我们的
想法。
public interface Sourceable {
public void method();
}
public class Source implements Sourceable {
@Override
public void method() {
System.out.println("the original method!");
}
}
public class Proxy implements Sourceable {
private Source source;
public Proxy(){
super();
this.source = new Source();
}
@Override
public void method() {
before();
source.method();
atfer();
}
private void atfer() {
System.out.println("after proxy!");
}
private void before() {
System.out.println("before proxy!");
}
}
public class ProxyTest {
public static void main(String[] args) {
Sourceable source = new Proxy();
source.method();
}
}
输出:
before proxy!
the original method!
after proxy!
代理模式的应用场景:
如果已有的方法在使用的时候需要对原有的方法进行改进,此时有两种办法:
1、修改原有的方法来适应。这样违反了“对扩展开放,对修改关闭”的原则。
2、就是采用一个代理类调用原有的方法,且对产生的结果进行控制。这种方法就是代理模式。
使用代理模式,可以将功能划分的更加清晰,有助于后期维护!
jdk动态代理
特点:只能对实现了接口的类生产代理,不能针对类
定义接口
/**
* 创建业务接口,包含业务可以提供对外的接口
*
*/
public interface UserService{
/**
* 目标方法
*/
public void add();
}
定义实现类
/**
* 创建业务接口实现类
*
*/
public class UserServiceImpl implements UserService{
@Override
public void add() {
System.out.println("----------add----------");
}
}
定义代理
/**
* 自定义简单的Invocation,对接口提供的方法进行增强
*
* @author Fighter
* @date 2016-04-19
*/
public class MyInvocationHandler implements InvocationHandler {
//目标对象
private Object target;
/**
* 构造方法
* @param target 目标对象
*/
public MyInvocationHandler(Object target) {
super();
this.target=target;
}
* 执行目标对象的方法
*/
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
//在目标方法执行前简单打印一下
System.out.println("----------before----------");
//执行目标方法对象
Object result=method.invoke(target, args);
//在目标方法执行之后简单打印一下
System.out.println("----------after----------");
return result;
}
/**
* 获取目标对象的代理对象
* @return 代理对象
* this.target.getClass().getInterfaces()//获取被代理对象实现的所有接口
*/
public Object getProxy(){
return Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),
this.target.getClass().getInterfaces(),this);
}
}
jdk动态代理测试
public class ProxyTest{
@Test
public void testProxy() throws Throwable{
//实例化目标对象
UserService userService=new UserServiceImpl();
//实例化Invocation
MyInvocationHandler invocationHandler=new MyInvocationHandler(userService);
//根据目标生成代理对象
UserService proxy=(UserService)invocationHandler.getProxy();
//调用代理对象方法
proxy.add();
}
}
CGLIB动态代理示例
DK的动态代理机制只能代理实现了接口的类,而不能实现接口的类就不能实现JDK的动态代理,cglib是针对
类来实现代理的,他的原理是对指定的目标类生成一个子类,并覆盖其中方法实现增强,但因为采用的是
继承,所以不能对final修饰的类进行代理。 CGLIB是一个强大的高性能的代码生成包。
定义实现类
/**
* 这个是没有实现接口的实现类
*
*/
public class BookFacadeImpl {
public void addBook() {
System.out.println("增加图书的普通方法...");
}
}
/**
* 使用cglib动态代理
*
*/
public class BookFacadeCglib implements MethodInterceptor {
private Object target;
/**
* 创建代理对象
*
* @param target
* @return
*/
public Object getInstance(Object target) {
this.target = target;
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(this.target.getClass());
// 回调方法
enhancer.setCallback(this);
// 创建代理对象
return enhancer.create();
}
@Override
// 回调方法
public Object intercept(Object obj, Method method, Object[] args,
MethodProxy proxy) throws Throwable {
System.out.println("事物开始");
proxy.invokeSuper(obj, args);
System.out.println("事物结束");
return null;
}
}
public class TestCglib {
public static void main(String[] args) {
BookFacadeCglib cglib=new BookFacadeCglib();
BookFacadeImpl bookCglib=(BookFacadeImpl)cglib.getInstance(new BookFacadeImpl());
bookCglib.addBook();
}
}
总结
CGLib创建的动态代理对象性能比JDK创建的动态代理对象的性能高不少,但是CGLib在创建代理对象时所
花费的时间却比JDK多得多,所以对于单例的对象,因为无需频繁创建对象,用CGLib合适,反之,使用JDK
方式要更为合适一些。同时,由于CGLib由于是采用动态创建子类的方法,对于final方法,无法进行代理。