结构型之代理模式
序言
代理模式可以实现对被代理对象的间接控制,可以对被代理对象的方法进行增强,她不重写原有的方法。
代理模式基本分为3类:
- jdk静态代理: 1个代理类只能代理1个类,局限性较大。
- jdk动态代理: 1个代理类能代理多个类,要求被代理类必须要有接口,利用了反射,效率比较低。
- cglib动态代理:1个代理类能代理多个类,被代理类不需要有接口,效率较高,不能代理final的类和方法
1. jdk静态代理模式
套路:
- 代理类要实现被代理类的接口,使代理类的方法与被代理类的保持一致。
- 代理类要加入一个被代理类的委托对象,由客户端初始化。
- 添加私有的增强方法。
/**
* 登录接口
*/
public interface LoginService {
public void login();
}
/**
* 登录接口代理对象
*/
public class LoginServiceProxy implements LoginService{
private LoginService loginService;
public LoginServiceProxy(LoginService loginService){
this.loginService = loginService;
}
public void login() {
preLogin();
loginService.login();
postLogin();
}
private void preLogin(){
System.out.println("=====登录前认证校验=====");
}
private void postLogin(){
System.out.println("=====登录后日志记录=====");
}
}
/**
* 登录接口实现类
*/
public class LoginServiceImpl implements LoginService{
public void login() {
System.out.println("正在登录...");
}
}
/**
* jdk静态代理测试
*/
public class JdkStaticProxyTest {
@Test
public void testJdkStaticProxy(){
LoginServiceProxy loginServiceProxy = new LoginServiceProxy(new LoginServiceImpl());
loginServiceProxy.login();
}
}
2. jdk动态代理模式
/**
* 登录接口
*/
public interface LoginService {
public void login();
}
/**
* 登录接口实现类
*/
public class LoginServiceImpl implements LoginService {
public void login() {
System.out.println("正在登录...");
}
}
/**
* 登录接口代理对象
*/
public class ServiceInvocationHandler implements InvocationHandler {
//被代理对象
private Object target;
public ServiceInvocationHandler(Object object){
this.target = object;
}
private void preOperation(){
System.out.println("=====执行前校验=====");
}
private void postOperation(){
System.out.println("=====执行后记录日志=====");
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
preOperation();
Object result = method.invoke(target, args);
postOperation();
return result;
}
public Object getProxy() throws Throwable {
return Proxy.newProxyInstance(Thread.currentThread()
.getContextClassLoader(), this.target.getClass()
.getInterfaces(), this);
}
}
/**
* jdk静态代理测试
*/
public class JdkDynamicProxyTest {
@Test
public void testJdkStaticProxy() throws Throwable {
LoginService proxy = (LoginService) new ServiceInvocationHandler(new LoginServiceImpl()).getProxy();
proxy.login();
System.out.println(proxy.getClass());
}
}
3. cglib动态代理模式
/**
* 登录类
*/
public class LoginServiceImpl{
public void login() {
System.out.println("正在登录...");
}
}
/**
* 登录接口代理对象
*/
public class LoginServiceProxy implements MethodInterceptor{
private Object target;
public LoginServiceProxy(Object obj){
this.target = obj;
}
public Object getInstance(){
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(this.target.getClass());
enhancer.setCallback(this); //设置回调方法
return enhancer.create(); //创建代理对象
}
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
preOpteration();
Object result = methodProxy.invokeSuper(o, objects);
postOpteration();
return result;
}
private void preOpteration(){
System.out.println("=====执行前校验=====");
}
private void postOpteration(){
System.out.println("=====执行后记录日志=====");
}
}
/**
* cglib动态代理测试
*/
public class CglibProxyTest {
@Test
public void testCglibProxy(){
LoginServiceImpl loginServiceProxy = (LoginServiceImpl) new LoginServiceProxy(new LoginServiceImpl()).getInstance();
loginServiceProxy.login();
}
}
后记
- 撰写本文考了不少博文,在此一并谢过。
Java代理(jdk静态代理、动态代理和cglib动态代理)
《JAVA与模式》之代理模式- 转载时,请注明出处,这是人格的一种体现。
https://www.zybuluo.com/BertLee/note/845369- 能力有限,如有纰漏,请在评论区指出,老朽虽一把年纪,必当感激涕零,泪如雨下。若有满嘴喷粪撕逼者,一律拉黑、举报。