代理模式是指,为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户类和目标对象之间起到中介的作用
使用代理对象,是为了在不修改目标对象的基础上,增强主业务逻辑。
客户类真正的想要访问的对象是目标对象,但客户类真正可以访问的对象是代理对象。客户类对目标对象的访问是通过访问代理对象来实现的。当然,代理类与目标类要实现同一个接口。
代理模式
一、静态代理
有代理类
二、JDK动态代理
接口类
public interface ISomeService {
String doFirst();
void doSecond();
}
实现类
public class SomeServiceImpl implements ISomeService{
@Override
public String doFirst() {
System.out.println("doFirst()方法");
return "abecd";
}
@Override
public void doSecond() {
System.out.println("doSecond()方法");
}
}
测试类
public class MyTest {
@Test
public void proxyTest() {
final ISomeService target = new SomeServiceImpl();
/*
由Proxy类的newProxyInstance()方法生成一个动态代理对象
loader:目标类的类加载器
interfaces:目标类所实现的所有接口
h:匿名内部类
*/
ISomeService service = (ISomeService) Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), new InvocationHandler() {
@Override
/*
proxy:代理对象
method:目标方法
args:目标方法的参数列表
*/
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object result = method.invoke(target, args);
if (result != null){
result = ((String) result).toUpperCase();
return result;
}
return result;
}
});
String result = service.doFirst();
System.out.println(result);
service.doSecond();
}
}
结果
doFirst()方法
ABECD
doSecond()方法
三、CGLIB动态代理
使用JDK的Proxy实现代理,要求目标类与代理类实现相同的接口。若目标类不存在接口,则无法使用该方式实现。
但对于无接口的类,要为其创建动态代理,就要使用CGLIB来实现。CGLIB代理的生成原理是生成目标类的子类,而子类是增强过的,这个子类对象就是代理对象。所以,使用CGLIB生成动态代理,要求目标类必须能够被继承,而不能是final的类。
(1)、无接口的CGLIB动态代理实现
无接口类
SomeService.java
//目标类:没有实现任何接口
public class SomeService {
public String doFirst() {
System.out.println("执行doFirst()方法");
return "abcdef";
}
public void doSecond() {
System.out.println("执行doSecond()方法");
}
}
CglibFactory.java
/*
注意:使用cglib动态代理,要求目标类不能是final的
因为final类是不能有子类的,而cglib动态代理的增强的原理是:子类增强父类
*/
public class CglibFactory implements MethodInterceptor{
private SomeService target;
public CglibFactory() {
}
public CglibFactory(SomeService target) {
this.target = target;
}
public SomeService myCglibCreator() {
Enhancer enhancer = new Enhancer();
//指定父类,即目标类。因为cglib动态代理增强的原理是:子类增强父类
enhancer.setSuperclass(SomeService.class);
//设置回调接口对象
enhancer.setCallback(this);
//creat()方法用于创建cglib动态代理对象,即目标类的子类对象
return (SomeService)enhancer.create();
}
//回调接口的方法
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
Object invoke = method.invoke(target, args);
if (invoke != null) {
invoke = ((String)invoke).toUpperCase();
}
return invoke;
}
}
测试
public class myCglibTest {
@Test
public void test() {
SomeService target = new SomeService();
SomeService service = new CglibFactory(target).myCglibCreator();
String result = service.doFirst();
System.out.println(result);
service.doSecond();
}
}
结果
执行doFirst()方法
ABCDEF
执行doSecond()方法
(2)、有接口的CGLIB动态代理实现
**CglibFatoryI.java
public class CglibFactoryI implements MethodInterceptor{
private ISomeService target;
public CglibFactoryI() {
}
public CglibFactoryI(ISomeService target) {
this.target = target;
}
public ISomeService myCglibCreator() {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(ISomeService.class);
enhancer.setCallback(this);
return (ISomeService) enhancer.create();
}
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
Object invoke = method.invoke(target, args);
if (invoke != null) {
invoke = ((String)invoke).toUpperCase();
}
return invoke;
}
}
测试
//有接口的CGLIB动态代理实现
@Test
public void test2() {
ISomeService target = new SomeServiceImpl();
ISomeService service = new CglibFactoryI(target).myCglibCreator();
String result = service.doFirst();
System.out.println(result);
service.doSecond();
}
结果
doFirst()方法
ABECD
doSecond()方法