aop 实现有两种方式
1. ProxyFactoryBean方式: 这种方式是通过配置实现
2. ProxyFactory方式:这种方式是通过编程实现
这里说 ProxyFactoryBean ,先上一张ProxyFactoryBean 的关系图,后面能用到。
示例代码:
/**
* 代理接口,如果不是接口使用CGLIB代理
*/
public interface ProxyInterface {
void m();
void t();
}
/**
* 目标对象,接口的实现类
*/
public class Target implements ProxyInterface {
@Override
public void m() {
System.out.println("m");
}
@Override
public void t() {
System.out.println("t");
}
}
/**
* 通知器
*/
public class BeforeAdvice implements MethodBeforeAdvice {
@Override
public void before(Method method, Object[] args, Object target) throws Throwable {
System.out.println("BeforeAdvice.....");
}
}
/**
* 通知器
*/
public class AfterAdvice implements AfterReturningAdvice {
@Override
public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
System.out.println("AfterAdvice.....");
}
}
定义一个接口ProxyInterface, 实现类为 Target,声明了两个advice,用来增强Target 方法。配置文件如下(advice 配置的顺序就是调用的顺序):
<?xml version="1.0" encoding="UTF-8"?>
<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-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">
<!-- 目标类 -->
<bean id="target" class="com.masz.springtest.aop.proxy.Target"/>
<!-- advice -->
<bean id="beforeAdvice" class="com.masz.springtest.aop.proxy.BeforeAdvice"/>
<bean id="afterAdvice" class="com.masz.springtest.aop.proxy.AfterAdvice"/>
<!-- 增强代理对象,ProxyFactoryBean 是一个FactoryBean , getBean() 时会调用它的getObject() 方法 -->
<bean id="targetProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
<!-- 代理接口,如果没有接口使用CGLIB生成代理类-->
<property name="proxyInterfaces">
<list>
<value>com.masz.springtest.aop.proxy.ProxyInterface</value>
</list>
</property>
<property name="singleton" value="true"/> <!-- 是否是单例 -->
<property name="target" ref="target"/> <!-- 指定增强目标bean -->
<!-- 拦截器名称 -->
<property name="interceptorNames">
<list>
<value>beforeAdvice</value>
<value>afterAdvice</value>
</list>
</property>
</bean>
</beans>
测试:
public static void main(String[] args) {
ConfigurableApplicationContext applicationContext = SpringApplication.run(AopTest.class, args);
//直接获取目标类
Target t = applicationContext.getBean(Target.class);
t.m();
//获取目标的代理。 关键的是:ProxyFactoryBean 是一个FactoryBean
ProxyInterface proxy = (ProxyInterface)applicationContext.getBean("targetProxy");
proxy.m();
System.exit(0);
}
运行结果:
m
BeforeAdvice.....
m
AfterAdvice.....
第一个方法没有被增强,第二个方法被增强了。
源码分析:
从代码中可以看到,通过applicationContext.getBean()获取ProxyFactoryBean, ProxyFactoryBean 是一个FactoryBean 所以getObject() 方法就是获取代理对象的入口方法。
ProxyFactoryBean.getObject() 源码:
@Override
@Nullable
public Object getObject() throws BeansException {
//初始化advisor 链
initializeAdvisorChain();
//对si