一.定义与类型
1.定义:为其他对象提供一种代理,以控制对这个对象的访问
代理对象在客户端和目标对象之间起到中介的作用
2.类型:结构型
二.适用场景
1.保护目标对象
2.增强目标对象
三.优点
1.代理模式能将代理对象与真实被调用的目标对象分离
2.一定程度上降低了系统的耦合度,扩展性好
3.保护目标对象
4.增强目标对象
四.缺点
1.代理模式会造成系统设计中类的数目增加
2.在客户端和目标对象增加一个代理对象,会造成请求处理速度变慢
3.增加了系统的复杂度
五.扩展
1.静态代理
在代码中显示指定的代理
2.动态代理
只能对实现的接口的类实现代理,并不能针对一个具体的实现类
3.CGLib代理
可以代理类,针对类实现进行代理
六.Spring代理选择
1.当Bean有实现接口时,Spring就会用JDK的动态代理
2.当Bean没有实现接口时,Spring使用CGlib
3.可以强制使用Cglib
在spring配置中加入<aop:aspectj-autoproxy proxy-target-class="true"/>
七.代理速度对比
1.万次执行情况下,JDK7和JDK8的动态代理性能要比CGLib大约快20%左右
8.UML
9.j静态代理代码
IOrderDao.java
package com.caomingyu.autotest.proxy;
public interface IOrderDao {
int insert(Order order);
}
IOrderService
package com.caomingyu.autotest.proxy;
public interface IOrderService {
int saveOrder(Order order);
}
OrderDaoImpl.java
package com.caomingyu.autotest.proxy;
public class OrderDaoImpl implements IOrderDao {
public int insert(Order order) {
System.out.println("Dao层添加Order成功");
return 1;
}
}
OrderServiceImpl.java
package com.caomingyu.autotest.proxy;
public class OrderServiceImpl implements IOrderService {
private IOrderDao iOrderDao;
public int saveOrder(Order order) {
iOrderDao = new OrderDaoImpl();
System.out.println("Service层调用Dao层添加Order");
return iOrderDao.insert(order);
}
}
OrderServiceStaticProxy.java
package com.caomingyu.autotest.proxy.staticproxy;
import com.caomingyu.autotest.proxy.IOrderService;
import com.caomingyu.autotest.proxy.Order;
import com.caomingyu.autotest.proxy.OrderServiceImpl;
import com.caomingyu.autotest.proxy.db.DataSourceContextHolder;
public class OrderServiceStaticProxy {
private IOrderService iOrderService;
public int saveOrder(Order order){
beforeMethod(order);
iOrderService = new OrderServiceImpl();
int result = iOrderService.saveOrder(order);
afterMethod();
return result;
}
private void beforeMethod(Order order){
int userId = order.getUserId();
int dbRouter = userId % 2;
System.out.println("静态代理分配到 【db" + dbRouter + "】处理数据");
//设置dataSource
DataSourceContextHolder.setDBType("db" + String.valueOf(dbRouter));
System.out.println("静态代理 before code");
}
private void afterMethod(){
System.out.println("静态代理 after code");
}
}
Test.java
package com.caomingyu.autotest.proxy.staticproxy;
import com.caomingyu.autotest.proxy.Order;
public class Test {
public static void main(String[] args) {
Order order = new Order();
order.setUserId(1);
OrderServiceStaticProxy orderServiceStaticProxy = new OrderServiceStaticProxy();
orderServiceStaticProxy.saveOrder(order);
}
}
10.动态代理代码
只要把OrderServiceStaticProxy.java换成OrderServiceDynamicProxy.java
package com.caomingyu.autotest.proxy.dynamicproxy;
import com.caomingyu.autotest.proxy.Order;
import com.caomingyu.autotest.proxy.db.DataSourceContextHolder;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class OrderServiceDynamicProxy implements InvocationHandler {
private Object target;
public OrderServiceDynamicProxy(Object target) {
this.target = target;
}
public Object bind(){
Class cls = target.getClass();
return Proxy.newProxyInstance(cls.getClassLoader(), cls.getInterfaces(), this);
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object argObject = args[0];
beforeMethod(argObject);
Object object = method.invoke(target,args);
afterMethod();
return object;
}
private void beforeMethod(Object obj){
int userId = 0;
System.out.println("动态代理 before code");
if (obj instanceof Order){
Order order = (Order) obj;
userId = order.getUserId();
}
int dbRouter = userId % 2;
System.out.println("动态代理分配到 【db" + dbRouter + "】处理数据");
//设置dataSource
DataSourceContextHolder.setDBType("db" + String.valueOf(dbRouter));
System.out.println("动态代理 before code");
}
private void afterMethod(){
System.out.println("动态代理 after code");
}
}
Test.java
package com.caomingyu.autotest.proxy.dynamicproxy;
import com.caomingyu.autotest.proxy.IOrderService;
import com.caomingyu.autotest.proxy.Order;
import com.caomingyu.autotest.proxy.OrderServiceImpl;
public class Test {
public static void main(String[] args) {
Order order = new Order();
order.setUserId(2);
IOrderService orderServiceDynamicProxy = (IOrderService) new OrderServiceDynamicProxy(new OrderServiceImpl()).bind();
orderServiceDynamicProxy.saveOrder(order);
}
}