如果把《spring-beans核心容器》比较树干,spring-aop则是其树枝。使其在固定的生命周期之外拥有不一样的分枝。
spring aop的配置可以通过xml文件来进行,大概有四种方式:
1,2方式是基于《浅谈AOP》的 aop alliance规范
3,4方式则是使用了AspectJ规范
以下是其配置方式(省略部分代码)
<bean id="admin" class="entity.AdminUser" autowire="byType">
<property name="username" value="eeeerrrr">property>
bean>
<bean id="aspect" class="entity.MyAspect">bean>
<bean class="org.springframework.aop.framework.ProxyFactoryBean" id="adminProxy">
<property name="target" ref="admin">property>
<property name="interceptorNames" value="aspect">property>
<property name="proxyTargetClass" value="true">property>
bean>
public class MyAspect implements MethodInterceptor {
@Override
public Object invoke(MethodInvocation methodInvocation) throws Throwable {
System.out.println("方法被调用["+methodInvocation.getMethod().getName() + "]");
return methodInvocation.proceed();
}
}
Resource resource = new ClassPathResource("spring-aop.xml");
//创建bean工厂
DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
/解析配置,并注册bean到工厂中
BeanDefinitionReader context=new XmlBeanDefinitionReader(factory);
context.loadBeanDefinitions(resource);
//从工厂中取出对象
AdminUser user = (AdminUser) factory.getBean("admin");
System.out.println(user.getUsername());
//符合FactoryBean的特性,取到了原对象
ProxyFactoryBean proxyFactoryBean = (ProxyFactoryBean) factory.getBean("&adminProxy");
System.out.println(proxyFactoryBean.getClass());
提供被代理对象的类型
//提供代理类的类型
Class<?> getTargetClass();
获取代理的配置信息
//冻结配置,冻结后配置都走缓存。
boolean isFrozen();
//是否采用继承类代理
boolean isProxyTargetClass();
//被代理对象所实现的接口集
Class<?>[] getProxiedInterfaces();
//是否被代理对象所实现的接口
boolean isInterfaceProxied(Class<?> intf);
//获取被代理对象
TargetSource getTargetSource();
//是否爆露代理对象
//如果爆路,在执行真实方法前,会把代理对象放到ThreadLocal中, 真实方法中可取
//@see AopContext.setCurrentProxy(proxy)
boolean isExposeProxy();
//是否开启ClassFilter过滤功能,来过滤一些不想作用的切点
boolean isPreFiltered();
//查询所有的切点
Advisor[] getAdvisors();
代理的基本配置信息
//是否采用继承类代理
private boolean proxyTargetClass = false;
//是否系统自动选择代理
private boolean optimize = false;
//如果代理类继续Advised,是否爆露
//@see AopProxyUtils.completeProxiedInterfaces
boolean opaque = false;
//是否爆露代理对象
boolean exposeProxy = false;
//冻结配置,冻结后配置都走缓存。
private boolean frozen = false;
扩展ProxyConfig对Advised的具体实现。
//被代理对象,默认为一空值
TargetSource targetSource = EMPTY_TARGET_SOURCE;
//是否开启ClassFilter过滤功能,来过滤一些不想作用的advisor
private boolean preFiltered = false;
//advisor获取策略,主要是根据一定规则筛选出advisor,例如preFiltered
AdvisorChainFactory advisorChainFactory = new DefaultAdvisorChainFactory();
//缓存method-advisors的Map,不用重新根据规则计算advisor
private transient Map<MethodCacheKey, List<Object>> methodCache;
//被代理对象实现的接口
private List<Class<?>> interfaces = new ArrayList<>();
//所有的切点
private List<Advisor> advisors = new ArrayList<>();
//advisors的数组缓存
private Advisor[] advisorArray = new Advisor[0];
//根据对象的方法及class结合advisorChainFactory筛选出advisor
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(Method method, @Nullable Class<?> targetClass)
适配器,将代理配置,提供给代理工厂,创建代理。
//选择代理策略
//如果代理类不是接口且本身不是代理类且 proxyTargetClass 或者 optimize 或者 代理类没接口 选用继承
private AopProxyFactory aopProxyFactory;
//代理配置修改监听类
private final List<AdvisedSupportListener> listeners = new LinkedList();
通过FactoryBean.getObject的方式,切入bean的生命周期。
public Object getObject() throws BeansException {
//将设置的interceptorNames,转化成Advisor放进代理配置里面
initializeAdvisorChain();
return getSingletonInstance();
}
private synchronized Object getSingletonInstance() {
//createAopProxy,根据代理配置创建代理对象工厂,cglib 还是 jdk proxy
//getProxy 根据代理对象工厂,结合被代理对象,具体返回值
this.singletonInstance = getProxy(createAopProxy());
return this.singletonInstance;
}
以下是其配置方式(省略部分代码)
//引用配置文件
Resource resource = new ClassPathResource("spring-aop.xml");
//创建bean工厂
DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
//创建BeanPostProcessor加入factory
BeanNameAutoProxyCreator beanNameAutoProxyCreator = new BeanNameAutoProxyCreator();
beanNameAutoProxyCreator.setBeanNames("admin");
beanNameAutoProxyCreator.setInterceptorNames("aspect");
beanNameAutoProxyCreator.setBeanFactory(factory);
factory.addBeanPostProcessor(beanNameAutoProxyCreator);
//解析配置,并注册bean到工厂中
BeanDefinitionReader context=new XmlBeanDefinitionReader(factory);
context.loadBeanDefinitions(resource);
//从工厂中取出对象
AdminUser user = (AdminUser) factory.getBean("admin");
System.out.println(user.getUsername());
在ProxyConfig的基础上, 增加processor的order配置,容器的加载配置。
//processor的顺序配置
private int order = Ordered.LOWEST_PRECEDENCE;
//加载器配置
private ClassLoader proxyClassLoader = ClassUtils.getDefaultClassLoader();
//是否可自定义加载器
private boolean classLoaderConfigured = false;
通过BeanPostProcessor.postProcessBeforeInstantiation的方式,切入bean的生命周期。
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {
//获取被代理对象
TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
//抽象方法,根据具体实现返回代理的接口
//为null则表示不代理
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
return proxy;
}
protected Object createProxy(Class<?> beanClass, String beanName,
@Nullable Object[] specificInterceptors, TargetSource targetSource) {
//创建ProxyFactory,相当于ProxyCreatorSupport
ProxyFactory proxyFactory = new ProxyFactory();
//复制proxyConfig
proxyFactory.copyFrom(this);
//根据当前配置修改代理策略
if (!proxyFactory.isProxyTargetClass()) {
if (shouldProxyTargetClass(beanClass, beanName)) {
proxyFactory.setProxyTargetClass(true);
}
else {
evaluateProxyInterfaces(beanClass, proxyFactory);
}
}
//如果specificInterceptors为null返回空
//如果不为null,将interceptorNames和specificInterceptors转为Advisor
Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
proxyFactory.addAdvisors(advisors);
proxyFactory.setTargetSource(targetSource);
customizeProxyFactory(proxyFactory);
proxyFactory.setFrozen(this.freezeProxy);
if (advisorsPreFiltered()) {
proxyFactory.setPreFiltered(true);
}
//创建代理
return proxyFactory.getProxy(getProxyClassLoader());
}
制定根据beanName来决定是否代理
protected Object[] getAdvicesAndAdvisorsForBean(
Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {
if (this.beanNames != null) {
//名称匹配还在别名匹配
for (String mappedName : this.beanNames) {
if (FactoryBean.class.isAssignableFrom(beanClass)) {
if (!mappedName.startsWith(BeanFactory.FACTORY_BEAN_PREFIX)) {
continue;
}
mappedName = mappedName.substring(BeanFactory.FACTORY_BEAN_PREFIX.length());
}
if (isMatch(beanName, mappedName)) {
return PROXY_WITHOUT_ADDITIONAL_INTERCEPTORS;
}
BeanFactory beanFactory = getBeanFactory();
if (beanFactory != null) {
String[] aliases = beanFactory.getAliases(beanName);
for (String alias : aliases) {
if (isMatch(alias, mappedName)) {
return PROXY_WITHOUT_ADDITIONAL_INTERCEPTORS;
}
}
}
}
}
//beanNames为空直接代理
return DO_NOT_PROXY;
}
因为其引用了AspectJ规范,所以要引入aspectjweaver。以下是其配置方式(省略部分代码)
<bean id="aspect" class="entity.MyAspect2">bean>
<aop:config>
<aop:pointcut id="myPoint" expression="execution(* *.*.*(..))"/>
<aop:aspect id="aspect" ref="aspect" order="1" >
<aop:before method="myBefore" pointcut-ref="myPoint">aop:before>
<aop:after method="myAfter" pointcut-ref="myPoint" >aop:after>
<aop:after-returning method="myAfterReturning" returning="result1" pointcut-ref="myPoint">aop:after-returning>
<aop:around method="myAround" pointcut-ref="myPoint">aop:around>
<aop:after-throwing method="myThrow" pointcut-ref="myPoint" throwing="throwable">aop:after-throwing>
aop:aspect>
aop:config>
//引用配置文件
Resource resource = new ClassPathResource("spring-aop.xml");
//创建bean工厂
DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
//解析配置,并注册bean到工厂中
//解析aop:config时
// 1.会注册 AspectJAwareAdvisorAutoProxyCreator 的BeanDefinition
// 2.解析 aop:before 注册 AspectJPointcutAdvisor#0 的BeanDefinition
//@see ConfigBeanDefinitionParser
//@see AopConfigUtils.registerAspectJAutoProxyCreatorIfNecessary
BeanDefinitionReader context=new XmlBeanDefinitionReader(factory);
context.loadBeanDefinitions(resource);
//初始化 aspectJAwareAdvisorAutoProxyCreator 并作为 BeanPostProcessor 加入
AspectJAwareAdvisorAutoProxyCreator aspectJAwareAdvisorAutoProxyCreator = (AspectJAwareAdvisorAutoProxyCreator) factory.getBean(AopConfigUtils.AUTO_PROXY_CREATOR_BEAN_NAME);
factory.addBeanPostProcessor(aspectJAwareAdvisorAutoProxyCreator);
//从工厂中取出对象
AdminUser user = (AdminUser) factory.getBean("admin");
System.out.println(user.getUsername());
把配置文件解析出来的AspectJPointcutAdvisor实体化,并进行匹配。
//实现根据beanClass查找切面的功能
protected Object[] getAdvicesAndAdvisorsForBean(
Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {
List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
if (advisors.isEmpty()) {
return DO_NOT_PROXY;
}
return advisors.toArray();
}
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
//从容器中找到Advisor的BeanDefinition并加载
List<Advisor> candidateAdvisors = findCandidateAdvisors();
//根据类,及poincut的ClassFilter及其它过渡Advisor
List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
//给继承类扩展使用
extendAdvisors(eligibleAdvisors);
if (!eligibleAdvisors.isEmpty()) {
//排序切面,根据Advisor的order属性
eligibleAdvisors = sortAdvisors(eligibleAdvisors);
}
return eligibleAdvisors;
}
对AbstractAdvisorAutoProxyCreator的一些方法具体实现
//根据order属性排序
protected List<Advisor> sortAdvisors(List<Advisor> advisors)
与aop:config实现原理差不多,借助于注解而已。最终作用在AnnotationAwareAspectJAutoProxyCreator。
详情介绍(略)。
public class ProxyTest {
static interface Car{
void drive();
void recharge();
}
static class ElectricCar implements Car {
public void drive() {
System.out.println("Electric Car is Moving silently...");
this.recharge();
}
public void recharge() {
System.out.println("Electric Car is Recharging...");
}
}
static class MyMethodInterceptor implements InvocationHandler {
private Object actor;
public MyMethodInterceptor(Object actor) {
this.actor = actor;
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("Before: "+ method);
Object ret = method.invoke(actor,args);
System.out.println("After: "+method);
return ret;
}
}
public static void main(String[] args) throws Exception {
ElectricCar car = new ElectricCar();
Object obj = Proxy.newProxyInstance(ProxyTest.class.getClassLoader(),new Class[]{Car.class}, new MyMethodInterceptor(car));
Method method = Car.class.getDeclaredMethod("drive");
method.invoke(obj);
}
}
public class CglibTest {
static class MyMethodInterceptor implements MethodInterceptor {
public Object intercept(Object obj, Method method, Object[] arg, MethodProxy proxy) throws Throwable {
System.out.println("Before: "+ method);
Object object = proxy.invokeSuper(obj, arg);
System.out.println("After: "+method);
return object;
}
}
static class ElectricCar {
public void drive() {
System.out.println("Electric Car is Moving silently...");
this.recharge();
}
public void recharge() {
System.out.println("Electric Car is Recharging...");
}
}
public static void main(String[] args) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(ElectricCar.class);
enhancer.setCallback(new MyMethodInterceptor());
ElectricCar student = (ElectricCar)enhancer.create();
student.drive();
}
}
采用接口代理的进行了一次切面,调用drive
采用继承代理的进行了二次切面,调用drive
继承中this指的是父类自己。
从AOP层面证明了spring事务,使用接口代理时,在类中自己调用自己无效。
《SpringAop的三种配置方法:基于ProxyFactoryBean、基于AspectJ的xml,基于AspectJ的注解》