ProxyFactoryBean及相关内容(上)
1、通过Spring API创建Spring AOP代理的基本方法是使用org.springframework.aop.framework.ProxyFactoryBean
2、ProxyFactoryBean可以完全控制切入点和通知(advice)以及他们的顺序。(和其它工厂Bean实现方式是一样的,都引入了一个中间层)
假如有这样一种情况:定义了一个Bean的Id为foo的ProxyFactoryBean,那么引用foo这个对象,看到的将不是ProxyFactoryBean本身,而是ProxyFactoryBean这个类通过getObject()方法创建的对象。
getObject():将创建一个AOP代理包装一个目标对象。(ProxyFactoryBean通过这种方式达到代理的目的)
3、使用ProxyFactoryBean或者其它IoC相关类来创建AOP代理的最重要好处是因为通知和切入点也可以由IoC来管理。
4、当被代理类没有实现任何接口,使用CGLIB代理,否则使用JDK代理。
5、通过设置proxyTargetClass为true,可强制使用CGLIB代理(无论代理类是否实现接口)
6、如果目标类实现了一个(或者多个)接口,那么创建代理的类型将依赖ProxyFactoryBean的配置。(因为ProxyFactoryBean里有一个ProxyInterfaces属性,该属性可以查看该类实现了哪些接口)
7、如果ProxyFactoryBean的proxyInterfaces属性被设置为一个或者多个全限定接口名(包括包名、类名、完整的名称),基于JDK的代理将被创建。
8、如果ProxyFactoryBean的proxyInterfaces属性没有被设置,但是目标类实现了一个(或者更多)接口,那么ProxyFactoryBean将自动检测到这个目标类已经实现了至少一个接口,创建一个基于JDK的代理。
例子:创建基于接口的代理
ProxyFactoryBean工作原理:首先,定义了一个Id为personTarget的Bean,又定义了一个Id为myAdvisor的Bean,定义了一个Id为debugInterceptor的Bean,重点在接下来的定义,定义了一个Id为person的Bean,但是对应的并不是Person类,而是Spring提供的ProxyFactoryBean这个类,并且这个Bean配置里有一个属性名为proxyInterfaces的<property>配置,并且它的value值为Person的路径,另外一个<property>标签属性名称为targer并且指向personTarget(这个类是Person的具体实现类),当我们get()Id为person这个Bean时,返回的并不是ProxyFactoryBean的对象,而是ProxyFactoryBean里的getObject()返回的对象,它返回的是属性名为target指向的personTarget的对象,通过ProxyFactoryBean创建代理的时候,可以指定它的interceptor,interceptorNames属性,是一个集合,可以通过List、Value指定它的具体内容。

案例:(通过Spring API实现通知)
各种通知的类前面已经写好了,所以主要进行XML配置。
public interface BizLogic {
String save();
}
public class BizLogicImpl implements BizLogic {
@Override
public String save() {
System.out.println("BizLogicImpl: BizLogicImpl save");
return "BizLogicImpl save";
}
}
XML配置:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd"
default-autowire="constructor">
<bean id="afterReturningAdvice" class="springAPI.MoocAfterReturningAdvice" ></bean>
<bean id="beforeAdvice" class="springAPI.MoocBeforeAdvice" ></bean>
<bean id="methodInterceptor" class="springAPI.MoocMethodInterceptor" ></bean>
<bean id="throwsAdvice" class="springAPI.MoocThrowsAdvice" ></bean>
<bean id="pointcutBean" class="org.springframework.aop.support.NameMatchMethodPointcut">
<property name="mappedNames">
<list>
<value>sa*</value>
</list>
</property>
</bean>
<bean id="defaultAdvisor" class="org.springframework.aop.support.DefaultPointcutAdvisor">
<property name="advice" ref="beforeAdvice"></property>
<property name="pointcut" ref="pointcutBean"></property>
</bean>
<bean id="bizLogicImplTarget" class="springAPI.BizLogicImpl"></bean>
<bean id="bizLogicImpl" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="target"><ref bean="bizLogicImplTarget"/></property>
<property name="interceptorNames">
<list>
<value>afterReturningAdvice</value>
<value>beforeAdvice</value>
<value>methodInterceptor</value>
<!-- <value>throwsAdvice</value>
-->
</list>
</property>
</bean>
</beans>
测试:
@Test
public void testApi(){
ApplicationContext ac=new ClassPathXmlApplicationContext("spring-ioc.xml");
BizLogic bl=(BizLogic)ac.getBean("bizLogicImpl");
bl.save();
}
结果:
前置通知的方法:save springAPI.BizLogicImpl
环绕前通知实现了
BizLogicImpl: BizLogicImpl save
环绕后通知实现了
返回后通知方法执行了save springAPI.BizLogicImpl null
修改后的结果是最常用的方式,好处就是不需要在外部定义bean
如果直接在外部定义bean,有个坏处,就是我们可以通过id 直接get到原始的bean对象(这个Bean对象是没有经过任何的代理处理过的,所以这些advice是不会被执行的)
选中的部分一定会走JDK代理
<property name="proxyInterfaces">
<value> com.imooc.aop.api.BizLogic</value>
</property>
Proxying interfaces
ProxyFactoryBean
6.如果ProxyFactoryBean的proxyInterfaces属性被设置,
但是目标类实现了一个(或者更多)接口,那么ProxyFactoryBean将自动检测到这个目标类已经实现了至少一个接口,创建一个基于JDK的代理
ProxyFactoryBean
使用ProxyFactoryBean或者其他IoC相关类来创建AOP代理的最重要好处是通知和切入点也可以由IoC来管理
被代理类没有实现任何接口,使用CGLIB代理,否则JDK代理
通过设置proxyTargetClass为true,可强制使用CGLIB
如果目标类实现了一个(或者多个)接口,那么创建代理的类型将依赖ProxyFactoryBean的配置
如果ProxyFactoryBean的proxyInterfaces属性被设置为一个或者多个全限定接口名,基于JDK的代理将被创建
ProxyFactoryBean实现里getObject()方法创建的对象
getObject方法将创建一个AOP代理包装一个目标对象
ProxyFactoryBean
创建Spring AOP代理的基本方法是使用org.springframework.aop.framework.ProxyFactoryBean
这可以完全控制切入点和通知(advice)以及他们的顺序
ProxyFactoryBean及相关内容(上)
1、通过Spring API创建Spring AOP代理的基本方法是使用org.springframework.aop.framework.ProxyFactoryBean
2、ProxyFactoryBean可以完全控制切入点和通知(advice)以及他们的顺序。(和其它工厂Bean实现方式是一样的,都引入了一个中间层)
假如有这样一种情况:定义了一个Bean的Id为foo的ProxyFactoryBean,那么引用foo这个对象,看到的将不是ProxyFactoryBean本身,而是ProxyFactoryBean这个类通过getObject()方法创建的对象。
getObject():将创建一个AOP代理包装一个目标对象。(ProxyFactoryBean通过这种方式达到代理的目的)
3、使用ProxyFactoryBean或者其它IoC相关类来创建AOP代理的最重要好处是因为通知和切入点也可以由IoC来管理。
4、当被代理类没有实现任何接口,使用CGLIB代理,否则使用JDK代理。
5、通过设置proxyTargetClass为true,可强制使用CGLIB代理(无论代理类是否实现接口)
6、如果目标类实现了一个(或者多个)接口,那么创建代理的类型将依赖ProxyFactoryBean的配置。(因为ProxyFactoryBean里有一个ProxyInterfaces属性,该属性可以查看该类实现了哪些接口)
7、如果ProxyFactoryBean的proxyInterfaces属性被设置为一个或者多个全限定接口名(包括包名、类名、完整的名称),基于JDK的代理将被创建。
8、如果ProxyFactoryBean的proxyInterfaces属性没有被设置,但是目标类实现了一个(或者更多)接口,那么ProxyFactoryBean将自动检测到这个目标类已经实现了至少一个接口,创建一个基于JDK的代理。
例子:创建基于接口的代理
ProxyFactoryBean工作原理:首先,定义了一个Id为personTarget的Bean,又定义了一个Id为myAdvisor的Bean,定义了一个Id为debugInterceptor的Bean,重点在接下来的定义,定义了一个Id为person的Bean,但是对应的并不是Person类,而是Spring提供的ProxyFactoryBean这个类,并且这个Bean配置里有一个属性名为proxyInterfaces的<property>配置,并且它的value值为Person的路径,另外一个<property>标签属性名称为targer并且指向personTarget(这个类是Person的具体实现类),当我们get()Id为person这个Bean时,返回的并不是ProxyFactoryBean的对象,而是ProxyFactoryBean里的getObject()返回的对象,它返回的是属性名为target指向的personTarget的对象,通过ProxyFactoryBean创建代理的时候,可以指定它的interceptor,interceptorNames属性,是一个集合,可以通过List、Value指定它的具体内容。

案例:(通过Spring API实现通知)
各种通知的类前面已经写好了,所以主要进行XML配置。
public interface BizLogic {
String save();
}
public class BizLogicImpl implements BizLogic {
@Override
public String save() {
System.out.println("BizLogicImpl: BizLogicImpl save");
return "BizLogicImpl save";
}
}
XML配置:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd"
default-autowire="constructor">
<bean id="afterReturningAdvice" class="springAPI.MoocAfterReturningAdvice" ></bean>
<bean id="beforeAdvice" class="springAPI.MoocBeforeAdvice" ></bean>
<bean id="methodInterceptor" class="springAPI.MoocMethodInterceptor" ></bean>
<bean id="throwsAdvice" class="springAPI.MoocThrowsAdvice" ></bean>
<bean id="pointcutBean" class="org.springframework.aop.support.NameMatchMethodPointcut">
<property name="mappedNames">
<list>
<value>sa*</value>
</list>
</property>
</bean>
<bean id="defaultAdvisor" class="org.springframework.aop.support.DefaultPointcutAdvisor">
<property name="advice" ref="beforeAdvice"></property>
<property name="pointcut" ref="pointcutBean"></property>
</bean>
<bean id="bizLogicImplTarget" class="springAPI.BizLogicImpl"></bean>
<bean id="bizLogicImpl" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="target"><ref bean="bizLogicImplTarget"/></property>
<property name="interceptorNames">
<list>
<value>afterReturningAdvice</value>
<value>beforeAdvice</value>
<value>methodInterceptor</value>
<!-- <value>throwsAdvice</value>
-->
</list>
</property>
</bean>
</beans>
测试:
@Test
public void testApi(){
ApplicationContext ac=new ClassPathXmlApplicationContext("spring-ioc.xml");
BizLogic bl=(BizLogic)ac.getBean("bizLogicImpl");
bl.save();
}
结果:
前置通知的方法:save springAPI.BizLogicImpl
环绕前通知实现了
BizLogicImpl: BizLogicImpl save
环绕后通知实现了
返回后通知方法执行了save springAPI.BizLogicImpl null
使用ProxyFactoryBean或者其他Ioc相关类的优点
ProxyFactoryBeanSpring Aop代理最基础的核心类
外部调用bizLogicImplTarget和直接内部调用bean class=实现类一样 refbean 和外面写bean一样
使用匿名内部bean来隐藏目标和代理之间的区别
Proxying interfaces 配置
创建Spring AOP代理的基本方法是使用org.springframework.aop.framework.ProxyFactoryBean
可以完全控制切入点和通知(advice)以及他们的顺序
代理接口是什么意思?
Advice是拦截后的方法,有执行前Advice、执行后Advice等
Advisor包裹了“要拦截的方法的过滤器,也可以说是切入点”和“一个或多个Advice”(这个从DefaultPointAdvisor的配置可以看出来)
而ProxyFactoryBean则把targetBean也就是需要代理的bean和一个或多个Advisor联系起来了
ProxyFactoryBean2
ProxyFactoryBean
ProxyFactoryBean
ProxyFactoryBean2:
ProxyFactoryBean:
3
2
1