Spring设计模式剖析之代理模式
1.定义 给某对象提供一个代理对象,通过代理对象可以访问该对象的功能。主要解决通过代理去访问[不能直接访问的对象],例如
租房中介,你可以直接通过中介去了解房东的房源信息,此时中介就可以称为代理。
2.代理的实行方式,这里我们讲解2种:
(1).jdk动态代理[基于接口的动态代理]
(2).CGLib动态代理[基于子类的动态代理]
一、使用jdk动态代理的实现(最少实现一个接口)
1.创建 车主接口对象OwnerService
public interface OwnerService {
void rentingPay(String name);
}
2. 创建车主对象Owner
public class Owner implements OwnerService{
/**** * @param name */
@Override
public void rentingPay(String name){
System.out.println(name+" 来买车");
}
}
3.创建代理处理过程对象: GuaZiProxy 实现InvocationHandler 接口
public class GuaZiProxy implements InvocationHandler{
private Object instance;
public GuaZiProxy(Object instance) {
this.instance = instance;
}
//整个代理过程
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//修改,增强
args[0]="瓜子二手车替客户"+args[0]+"交买车钱";
return method.invoke(instance,args);
}
}
4.创建代理,并通过代理调用车主方法: JdkProxyTest
public class JdkProxyTest {
public static void main(String[] args)throws Exception {
//需要被创建代理的对象
OwnerService ownerService = new Owner();
//创建代理
OwnerService proxyOwnerService = (OwnerService) Proxy.newProxyInstance(
proxyOwnerService.getClass().getClassLoader(),
Owner.class.getInterfaces(), //被代理的对象实现的所有接口
//代理过程->InvocationHandler
new GuaZiProxy(proxyOwnerService)
);
proxyOwnerService.pay("黄晓明");
}
}
5运行结果如下:
瓜子二手车替客户黄晓明交买车钱
二、CGLib动态代理(MethodInterceptor(Callback)接口中的invoke来实现)
1.创建CarsProxy 继承MethodInterceptor 接口,其实和上面瓜子是一样的,就是继承的接口不一样
public class CarsProxy implements MethodInterceptor{
private Object instance;
public CarsProxy(Object instance) {
this.instance = instance;
}
//代理的过程
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
objects[0]="人人车替客户"+args[0]+"交买车钱";
return method.invoke(instance,objects);
}
}
2.创建测试类: CGLibProxyTest ,代码如下
public class CGLibProxyTest {
public static void main(String[] args) {
//给指定对象创建代理
Owner owner = new Owner();
//1.被代理的对象字节码
//2.代理的过程实现,需要实现接口MethodInterceptor->Callback
Owner proxyOwner = (Owner) Enhancer.create(Owner.class,new CarsProxy(owner));
proxyOwner.pay("找白纸");
}
}
3.运行结果
人人车替客户找白纸交买车钱
三、Spring AOP-动态代理
1.简介
基于SpringAOP可以实现非常强大的功能,例如声明式事务、基于AOP的日志管理、基于AOP的权限管理等功能,利
用AOP可以将重复的代码抽取,重复利用,节省开发时间,提升开发效率。Spring的AOP其实底层就是基于动态代理
而来,并且支持JDK动态代理和CGLib动态代理,动态代理的集中体现在 DefaultAopProxyFactory 类中,我们来解
析下 DefaultAopProxyFactory 类。
2.配置
如果我们不在aop的spring文件中配置<aop:config
proxy-target-class=“true”>的话,默认是使用jdk代理模式 如果配置了的话启用用CGLib动态代理
3.spring-aop.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
<!--userService-->
<bean id="userService" class="com.tukecloud.aop.service.UserServiceImpl"/>
<!--注册增强(切面)类-->
<bean id="log" class="com.tukecloud.aop.Log"/>
<!--AOP配置-->
<aop:config proxy-target-class="false">
<!--配置切面(切入点和通知的结合)-->
<aop:aspect ref="log">
<!--前置通知-->
<aop:before method="before" pointcut="execution(* com.tukecloud.aop.service.*.*(..))"></aop:before>
</aop:aspect>
</aop:config>
</beans>