五Spring-AOP--3AOP动态代理涉及的类
五Spring-AOP--3AOP动态代理涉及的类
5.5 Spring AOP动态代理涉及的类
5.5.1 ProxyConfig
用于创建代理的配置的父类,以确保所有代理创建者具有一致的属性
public class ProxyConfig implements Serializable {
// 标记是否直接对目标类进行代理,而不是通过接口产生代理
private boolean proxyTargetClass = false;
// 标记是否对代理进行优化。true:那么在生成代理对象之后,如果对代理配置进行了修改,已经创建的代理对象也不会获取修改之后的代理配置。
// 如果exposeProxy设置为true,即使optimize为true也会被忽略。
private boolean optimize = false;
// 标记是否需要阻止通过该配置创建的代理对象转换为Advised类型,默认值为false,表示代理对象可以被转换为Advised类型
//Advised接口其实就代表了被代理的对象(此接口是Spring AOP提供,它提供了方法可以对代理进行操作,比如移除一个切面之类的),它持有了代理对象的一些属性,通过它可以对生成的代理对象的一些属性进行人为干预
// 默认情况,我们可以这么完 Advised target = (Advised) context.getBean("opaqueTest"); 从而就可以对该代理持有的一些属性进行干预勒 若此值为true,就不能这么玩了
boolean opaque = false;
//标记代理对象是否应该被aop框架通过AopContext以ThreadLocal的形式暴露出去。
//当一个代理对象需要调用它【自己】的另外一个代理方法时,这个属性将非常有用。默认是是false,以避免不必要的拦截。
boolean exposeProxy = false;
//标记是否需要冻结代理对象,即在代理对象生成之后,是否允许对其进行修改,默认为false.
// 当我们不希望调用方修改转换成Advised对象之后的代理对象时,就可以设置为true 给冻结上即可
private boolean frozen = false;
//从其他config对象中,复制配置信息到当前config
public void copyFrom(ProxyConfig other) {
Assert.notNull(other, "Other ProxyConfig object must not be null");
this.proxyTargetClass = other.proxyTargetClass;
this.optimize = other.optimize;
this.exposeProxy = other.exposeProxy;
this.frozen = other.frozen;
this.opaque = other.opaque;
}
}
proxyConfig有两大实现类,如下:
advisedSupport负责管理某个beanclass的所有切面advisor和拦截器interceptor的管理,主要实现类是proxyFactory,创建代理的工厂类(创建代理,需要知道target,method,interface等信息,以及需要知道advice、pointcut等切面信息,将这些增强添加到target上,完成代理类的创建工作);
ProxyProcessorSupport负责
5.5.2 Advised
注意本质:
Advice: 通知,拦截器(是具体的一个增强方法)
**Advisor: 通知 + 切入点的适配器,每一个服务类(如logging),其内定义多个增强方法,每个可以根据advice+pointcut,构成一个advisor,也叫做切面 **
Advised: 包含所有的Advisor 和 Advice,提供add和remove方法,负责对两个对象的管理工作
该advised的实现类最终是ProxyFactory,用来创建代理目标targetsource的proxy。proxy需要注入包括拦截器、advice等内容。因此,advised接口的作用,就是保存一个代理对象target需要的所有的相关配置信息,如这个targetsource的所有的interceptor、advice等。
所有的代理对象都实现了该接口(我们就能够通过一个代理对象,获取这个代理对象怎么被代理出来的相关信息)
不管是JDKproxy,还是cglib proxy,代理出来的对象都实现了org.springframework.aop.framework.Advised接口;

Addvised接口负责对advice和advisor的管理,包括add和remove操作方法;同时,还包括保存的代理的接口、targetsource代理的目标类(aop代理的是targetsource对象)。
该接口需要被实现,该class持有aop 的proxyFactory的配置。该configuration包括interceptros,Advisors,以及被代理的interface。任何从spring获取的aop的代理对象,都可以投给该advised接口(就是aop代理对象,实现该advised接口),允许对其AOP的advice等进行操作。
主要作用:
该接口为proxyFactory提供对advice和advisor管理的方法。
public interface Advised extends TargetClassAware {
boolean isFrozen();
boolean isProxyTargetClass();
//返回被代理了的接口们
Class<?>[] getProxiedInterfaces();
// 检查这个指定的接口是否被代理了。。。
boolean isInterfaceProxied(Class<?> intf);
// 设置一个源。只有isFrozen为false才能调用此方法
//设置被代理的类(为targetSource)
void setTargetSource(TargetSource targetSource);
TargetSource getTargetSource();
}
5.5.2.1 AdvisedSupport
public class AdvisedSupport extends ProxyConfig implements Advised {
//advisor链。当一个Advice添加,会被wrap成advisor后添加到当前list
private List<Advisor> advisors = new ArrayList<>();
/** method为key,List<advisorChain>为value的methodCache缓存对象 */
private transient Map<MethodCacheKey, List<Object>> methodCache;
//提供advisorChainFactory。factory提供
AdvisorChainFactory advisorChainFactory = new DefaultAdvisorChainFactory();
// 这里需要注意的是:setTarget最终的效果其实也是转换成了TargetSource
// 也就是说Spring最终代理的 是放进去TargetSource让它去处理
//ProxyFactory中设置的target目标,最终会被包装成SingletonTargetSource对象
public void setTarget(Object target) {
setTargetSource(new SingletonTargetSource(target));
}
@Override
public void setTargetSource(@Nullable TargetSource targetSource) {
this.targetSource = (targetSource != null ? targetSource : EMPTY_TARGET_SOURCE);
}
//根据此配置,确定给定方法的MethodInterceptor列表
//该方法用来获取代理的方法上,对应的有效的所有的拦截器interceptor链
//将DefaultAdvisorChainFactory的方法代理到getInterceptorsAndDynamicInterceptionAdvice上
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(Method method, @Nullable Class<?> targetClass) {
//以待拦截的method对象,创建MethodCacheKey--缓存中的key
MethodCacheKey cacheKey = new MethodCacheKey(method);
//查询缓存
List<Object> cached = this.methodCache.get(cacheKey);
if (cached == null) {
/**…………………………………………………………………………生成拦截器chain………………………………………………………………………………………… */
//DefaultAdvisorChainFactory:生成通知器链的工厂,实现了interceptor链的获取过程
cached = this.advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice(
this, method, targetClass);
//缓存中存储(MethodCacheKey(method),InterceptorsAndDynamicInterceptionAdvice)
this.methodCache.put(cacheKey, cached);
}
return cached;
}
用于设置和保存下面三大信息:
- 设置被代理对象target
- 设置代理接口
- 设置通知advice
注册被代理的目标对象、advice和需要代理的接口interface。
提供了使用proxyFactory获取aopProxy时候,设置代理对象的target和interface的方法。
[另外请详细见AdvisorChainFactory](#5.5.5.1 AdvisorChainFactory)
AdvisedSupport
本身不会提供创建代理的任何方法,专注于生成拦截器链。委托给ProxyCreatorSupport
去创建代理对象
5.5.2.2 ProxyCreatorSupport
注册和触发监听器,借助[DefaultAopProxyFactory](#5.5.4.1 DefaultAopProxyFactory)获取代理AopProxy(jdk和cglib动态代理的封装)。
public class ProxyCreatorSupport extends AdvisedSupport {
//new了一个aopProxyFactory
//通过DefaultAopProxyFactory创建aopProxy
private AopProxyFactory aopProxyFactory;
public ProxyCreatorSupport() {
this.aopProxyFactory = new DefaultAopProxyFactory();
}
//包含对listener的add/remove的管理
private final List<AdvisedSupportListener> listeners = new LinkedList<>();
//子类调用该方法获取aop proxy。
protected final synchronized AopProxy createAopProxy() {
if (!this.active) {
activate();
}
//委托给AopProxyFactory,获取aopProxyfactory,然后createAopProxy创建AopProxy
return getAopProxyFactory().createAopProxy(this);
}
public AopProxyFactory getAopProxyFactory() {
return this.aopProxyFactory;
}
ProxyCreatorSupport继承AdvisedSupport,主要提供了createAopProxy方法,代理给[DefaultAopProxyFactory.createAopProxy()](#5.5.4.1 DefaultAopProxyFactory),用来得到用来生成代理对象的AopProxy对象(提供动态代理创建对象的类,包括cglib和JDK)。
该类的实现类,是三大创建代理对象的工厂proxyFactory:
5.5.2.3 ProxyFactory
使用场景:
通过配置<aop:aspectj-autoproxy/>(@EnableAspectJAutoProxy)
使用基于注解@AspectJ的Aspectj
风格的Aop代理。
public class ProxyFactory extends ProxyCreatorSupport {
//丰富的构造函数,设置proxyFactory所需要的基本配置信息
public ProxyFactory(Class<?> proxyInterface, Interceptor interceptor) {
addInterface(proxyInterface);
addAdvice(interceptor);
}
public Object getProxy() {
return createAopProxy().getProxy();
}
public Object getProxy(@Nullable ClassLoader classLoader) {
return createAopProxy().getProxy(classLoader);
}
// 注意:若调用此方法生成代理,就直接使用的是CGLIB的方式的
public static Object getProxy(TargetSource targetSource) {
if (targetSource.getTargetClass() == null) {
throw new IllegalArgumentException("Cannot create class proxy for TargetSource with null target class");
}
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.setTargetSource(targetSource);
proxyFactory.setProxyTargetClass(true);
return proxyFactory.getProxy();
}
提供获取代理proxy的能力——就是提供getProxy()方法。
注意:
proxyFactory同样与springIOC容器没有关系,可以手动创建代理并使用。但是,由于其所代理的target,是由new创建出来的,因此不能和springIOC容器融合,因此proxyFactory不像ProxyFactoryBean可以定制化方法,proxyFactory是由spring内部调用,会在autoProxyCreator(代理自动创建器)中使用。
例如:
public static void main(String[] args) {
//代理的对象需要new,不能依靠springIOC的自动注入bean,因此用作内部调用
ProxyFactory proxyFactory = new ProxyFactory(new HelloServiceImpl());
// 添加两个Advice,一个匿名内部类表示
proxyFactory.addAdvice((AfterReturningAdvice) (returnValue, method, args1, target) ->
System.out.println("AfterReturningAdvice method=" + method.getName()));
proxyFactory.addAdvice(new LogMethodBeforeAdvice());
HelloService proxy = (HelloService) proxyFactory.getProxy();
proxy.hello();
}
输出:
this is LogMethodBeforeAdvice
this is my method~~
AfterReturningAdvice method=hello
5.5.2.4 ProxyFactoryBean
通过该类可以自定义getObject方法,来获取代理的对象。
注意:
private String[] interceptorNames;
此为注册的advice的名称。
如果用注释方式,@aspect内除了@pointcut,每个@before、@after等的方法名,最后会生成一个advice增强实例;
如果是非注释方式,该名称就是具体的实现类,如下:
// 先定义一个前置通知
@Component("logMethodBeforeAdvice")
public class LogMethodBeforeAdvice implements MethodBeforeAdvice {
@Override
public void before(Method method, Object[] args, Object target) throws Throwable {
System.out.println("this is LogMethodBeforeAdvice");
}
}
可见,构建拦截器链的过程interceptorNames——advice——advisor——methodInterceptor或者InterceptorAndDynamicMethodMatcher
public class ProxyFactoryBean extends ProxyCreatorSupport
implements FactoryBean<Object>, BeanClassLoaderAware, BeanFactoryAware {
//需要植入target对象的advice的名称
private String[] interceptorNames;
private String targetName;
//重要的转换类(适配器类)
private AdvisorAdapterRegistry advisorAdapterRegistry = GlobalAdvisorAdapterRegistry.getInstance();
private transient BeanFactory beanFactory;
//advisorchain是否初始化过
private boolean advisorChainInitialized = false;
//单例缓存
private Object singletonInstance;
//类似于spring中的factoryBean.getObject方法,实现该方法来获取真正的bean
public Object getObject() throws BeansException {
//就是根据我们配置的interceptorNames来获取对应需要植入的切面的bean,并却转化成Advisor。将当前target所有的
//this.advisorChainInitialized:标示是否已进行过初始化,若以初始化则不再进行初始化。
initializeAdvisorChain();
//生成代理对象时,因为Spring中有singleton类型和prototype类型这两种不同的Bean,所以要对代理对象的生成做一个区分
if (isSingleton()) {
//生成singleton的代理对象,这个方法是ProxyFactoryBean生成AOPProxy代理对象的调用入口
return getSingletonInstance();
}
else {
if (this.targetName == null) {
logger.warn("Using non-singleton proxies with singleton targets is often undesirable. " +
"Enable prototype proxies by setting the 'targetName' property.");
}
// 生成原型的代理对象
return newPrototypeInstance();
}
}
//通过读取interceptorNames将BeanFactory工厂内对应的Advice,Advisor,MethodInterceptor
//通过AdvisorAdapterRegistry.wrap(Advice,需要有对应的AdvisorAdapter的支持才可以转换)转换为Advisor然后加载到执行链条中
private synchronized void initializeAdvisorChain() throws AopConfigException, BeansException {
if (this.advisorChainInitialized) {
return;
}
if (!ObjectUtils.isEmpty(this.interceptorNames)) {
// Globals can't be last unless we specified a targetSource using the property...
// 最后一个不能是全局的suffix *,除非我们指定了targetSource之类的
if (this.interceptorNames[this.interceptorNames.length - 1].endsWith(GLOBAL_SUFFIX) &&this.targetName == null && this.targetSource == EMPTY_TARGET_SOURCE) {
throw new AopConfigException("Target required after globals");
}
// Materialize interceptor chain from bean names.
for (String name : this.interceptorNames) {
// 如果拦截器的名称是以*结尾的,说明它要去全局里面都搜索出来
// 全局:去自己容器以及父容器中找,类型为Advisor.class以及Interceptor.class所有的,名称是以这个名称为开头的prefix的Bean.
// 最终也一样交给addAdvisorOnChainCreation(bean, name); 相当于一个批量处理吧 在特殊场景还是很有用处的
if (name.endsWith(GLOBAL_SUFFIX)) {
addGlobalAdvisor((ListableBeanFactory) this.beanFactory,
name.substring(0, name.length() - GLOBAL_SUFFIX.length()));
}
// 绝大部分情况肯定都走这里:精确匹配
else {
Object advice;
if (this.singleton || this.beanFactory.isSingleton(name)) {
// 从容器里把这个Bean拿出来~~~~~~~~~~~~~
advice = this.beanFactory.getBean(name);
}
// 多例的 这里每次都是new一个新的
else {
// It's a prototype Advice or Advisor: replace with a prototype.
// Avoid unnecessary creation of prototype bean just for advisor chain initialization.
advice = new PrototypePlaceholderAdvisor(name);
}
// 这个方法的作用还挺大的:将advice对象添加到通知器链中
//方法中首先会调用namedBeanToAdvisor(next)方法,将从ioc容器获取的普通对象转换成通知器Advisor对象,然后add加入factory的List<Advisor>对象中
addAdvisorOnChainCreation(advice, name);
}
}
}
this.advisorChainInitialized = true;
}
private void addAdvisorOnChainCreation(Object next, String name) {
// We need to convert to an Advisor if necessary so that our source reference
// matches what we find from superclass interceptors.
// 这里调用namedBeanToAdvisor做了一下适配:成统一的Advisor
Advisor advisor = namedBeanToAdvisor(next);
addAdvisor(advisor);
}
//namedBeanToAdvisor
private Advisor namedBeanToAdvisor(Object next) {
try {
return this.advisorAdapterRegistry.wrap(next);
}
}
//获取单例代理对象
private synchronized Object getSingletonInstance() {
// 如果是单例的,现在这里持有这个缓存 创建国就不会再创建了
if (this.singletonInstance == null) {
// 根据设置的targetName,去工厂里拿到这个bean对象(普通Bean被包装成SingletonTargetSource)
this.targetSource = freshTargetSource();
// 这一步是如果你手动没有去设置需要被代理的接口,Spring还是会去帮你找看你有没有实现啥接口,然后全部给你代理上。可见Spring的容错性是很强的
if (this.autodetectInterfaces && getProxiedInterfaces().length == 0 && !isProxyTargetClass()) {
// Rely on AOP infrastructure to tell us what interfaces to proxy.
Class<?> targetClass = getTargetClass();
if (targetClass == null) {
throw new FactoryBeanNotInitializedException("Cannot determine target class for proxy");
}
setInterfaces(ClassUtils.getAllInterfacesForClass(targetClass, this.proxyClassLoader));
}
// Initialize the shared singleton instance.
super.setFrozen(this.freezeProxy);
// createAopProxy()方法就是父类ProxyCreatorSupport的方法
// 其中JdkDynamicAopProxy和CglibAopProxy对getProxy()方法的实现,也请参考前面分析
this.singletonInstance = getProxy(createAopProxy());
}
return this.singletonInstance;
}
private synchronized Object newPrototypeInstance() {
if (logger.isTraceEnabled()) {
logger.trace("Creating copy of prototype ProxyFactoryBean config: " + this);
}
ProxyCreatorSupport copy = new ProxyCreatorSupport(getAopProxyFactory());
// The copy needs a fresh advisor chain, and a fresh TargetSource.
TargetSource targetSource = freshTargetSource();
copy.copyConfigurationFrom(this, targetSource, freshAdvisorChain());
if (this.autodetectInterfaces && getProxiedInterfaces().length == 0 && !isProxyTargetClass()) {
// Rely on AOP infrastructure to tell us what interfaces to proxy.
Class<?> targetClass = targetSource.getTargetClass();
if (targetClass != null) {
copy.setInterfaces(ClassUtils.getAllInterfacesForClass(targetClass, this.proxyClassLoader));
}
}
copy.setFrozen(this.freezeProxy);
if (logger.isTraceEnabled()) {
logger.trace("Using ProxyCreatorSupport copy: " + copy);
}
return getProxy(copy.createAopProxy());
}
以上是针对某个具体targetclass进行代理,并产生代理类。
开发示例如下:
1 与spring容器集成使用
// 先定义一个前置通知
@Component("logMethodBeforeAdvice")
public class LogMethodBeforeAdvice implements MethodBeforeAdvice {
@Override
public void before(Method method, Object[] args, Object target) throws Throwable {
System.out.println("this is LogMethodBeforeAdvice");
}
}
// 注册一个代理Bean
//手动创建proxyFactoryBean,需要手动设置Target,Interfaces,InterceptorNames信息。
@Bean
public ProxyFactoryBean proxyFactoryBean(HelloService helloService) {
ProxyFactoryBean factoryBean = new ProxyFactoryBean();
//代理的目标对象 效果同setTargetSource(@Nullable TargetSource targetSource)
// 此处需要注意的是,这里如果直接new,那么该类就不能使用@Autowired之类的注入 因此建议此处还是从容器中去拿
// 因此可以写在入参上(这也是标准的写法~~)
//factoryBean.setTarget(new HelloServiceImpl());
factoryBean.setTarget(helloService);
// setInterfaces和setProxyInterfaces的效果是相同的。设置需要被代理的接口,
// 若没有实现接口,那就会采用cglib去代理
// 需要说明的一点是:这里不设置也能正常被代理(若你没指定,Spring内部会去帮你找到所有的接口,然后全部代理上~~~~~~~~~~~~) 设置的好处是只代理指定的接口
factoryBean.setInterfaces(HelloService.class);
//factoryBean.setProxyInterfaces(new Class[]{HelloService.class});
// 需要植入进目标对象的bean列表 此处需要注意:这些bean必须实现 org.aopalliance.intercept.MethodInterceptor或 org.springframework.aop.Advisor的bean ,配置中的顺序对应调用的顺序
factoryBean.setInterceptorNames("logMethodBeforeAdvice");
// 若设置为true,强制使用cglib,默认是false的
//factoryBean.setProxyTargetClass(true);
return factoryBean;
}
// main方法测试:
public static void main(String[] args) {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(RootConfig.class);
//expected single matching bean but found 2: helloServiceImpl,proxyFactoryBean
// 如果通过类型获取,会找到两个Bean:一个我们自己的实现类、一个ProxyFactoryBean所生产的代理类 而此处我们显然是希望要生成的代理类的 因此我们只能通过名称来(或者加上@Primary)
//HelloService bean = applicationContext.getBean(HelloService.class);
HelloService bean = (HelloService) applicationContext.getBean("proxyFactoryBean");
bean.hello();
System.out.println(bean); //com.fsx.service.HelloServiceImpl@4e50c791
System.out.println(bean.getClass()); //class com.sun.proxy.$Proxy22 用得JDK的动态代理
// 顺便说一句:这样也是没错得。因为Spring AOP代理出来的每个代理对象,都默认实现了这个接口(它是个标记接口)
// 它这个也就类似于所有的JDK代理出来的,都是Proxy的子类是一样的思想~
SpringProxy springProxy = (SpringProxy) bean;
}
输出:
this is LogMethodBeforeAdvice
this is my method~~
注意区别:
//expected single matching bean but found 2: helloServiceImpl,proxyFactoryBean
// 如果通过类型获取,会找到两个Bean:一个我们自己的实现类、一个ProxyFactoryBean所生产的代理类 而此处我们显然是希望要生成的代理类的 因此我们只能通过名称来(或者加上@Primary)
//HelloService bean = applicationContext.getBean(HelloService.class);
HelloService bean = (HelloService) applicationContext.getBean("proxyFactoryBean");
2 脱离spring容器使用
proxyFactoryBean的生成代理的核心功能getProxy在父类ProxyCreatorSupport上,与容器无关,因此可以摆脱springIOC而独立手动创建使用。
此时,需要设置target(如果target有接口,设置interface),然后需要手动创建advice并转换为advisor,然后proxyFactoryBean.addAdvisor(advisor)添加。最后可以通过getObject获取aop增强的代理对象。
public class Main {
public static void main(String[] args) {
String pointcutExpression = "execution( int com.fsx.maintest.Person.run() )";
// =============================================================
//因为我们要使用AspectJ,所以此处采用AspectJProxyFactory,当然你也可以使用和容器相关的ProxyFactoryBean
ProxyFactoryBean factory = new ProxyFactoryBean();
factory.setTarget(new Person());
//AspectJProxyFactory factory = new AspectJProxyFactory(new Person());
//声明一个aspectj切点,一张切面
AspectJExpressionPointcut cut = new AspectJExpressionPointcut();
cut.setExpression(pointcutExpression); // 设置切点表达式
// 声明一个通知(此处使用环绕通知 MethodInterceptor )
Advice advice = (MethodInterceptor) invocation -> {
System.out.println("============>放行前拦截...");
Object obj = invocation.proceed();
System.out.println("============>放行后拦截...");
return obj;
};
//切面=切点+通知
// 它还有个构造函数:DefaultPointcutAdvisor(Advice advice); 用的切面就是Pointcut.TRUE,所以如果你要指定切面,请使用自己指定的构造函数
// Pointcut.TRUE:表示啥都返回true,也就是说这个切面作用于所有的方法上/所有的方法
// addAdvice();方法最终内部都是被包装成一个 `DefaultPointcutAdvisor`,且使用的是Pointcut.TRUE切面,因此需要注意这些区别
Advisor advisor = new DefaultPointcutAdvisor(cut, advice);
factory.addAdvisor(advisor);
//Person p = factory.getProxy();
Person p = (Person) factory.getObject();
// 执行方法
p.run();
p.run(10);
p.say();
p.sayHi("Jack");
p.say("Tom", 666);
}
}
class Person {
public int run() {
System.out.println("我在run...");
return 0;
}
public void run(int i) {
System.out.println("我在run...<" + i + ">");
}
public void say() {
System.out.println("我在say...");
}
public void sayHi(String name) {
System.out.println("Hi," + name + ",你好");
}
public int say(String name, int i) {
System.out.println(name + "----" + i);
return 0;
}
}
5.5.2.5 AspectJProxyFactory
该类支持使用编程的方式,用@AspectJ注解定义切面,不实现任何的接口,创建代理对象。
AspectJ
是目前大家最常用的 起到集成AspectJ
和Spring
,也就是我们平时长谈的:自动代理模式。它整个代理的过程全部交给Spring内部去完成,无侵入。
Demo体验
@Aspect
class MyAspect {
//会被解析、包装成一个advisor1对象
@Pointcut("execution(* hello(..))")
private void beforeAdd() {
}
//解析、包装成advisor2对象
@Before("beforeAdd()")
public void before1() {
System.out.println("-----------before-----------");
}
}
在上述切面类定义中我们定义了一个切面服务类aspect(采用注解@Aspect标注的),其对应了一个MethodBeforeAdvice
,实际上是一个AspectJMethodBeforeAdvice
,该Advice对应的是上面的before1()
方法,还对应了一个Pointcut
:是一个AspectJExpressionPointcut
。 该Advisor
的语义拦截所有的方法名为“hello”的方法在它之前执行MyAspect.before1()
方法。
如果我们现在需要创建一个代理对象,其需要绑定的Advisor
逻辑跟上面定义的切面类中定义的Advisor
类似。则我们可以进行如下编程:
public static void main(String[] args) {
AspectJProxyFactory proxyFactory = new AspectJProxyFactory(new HelloServiceImpl());
// 注意:此处得MyAspect类上面的@Aspect注解必不可少
proxyFactory.addAspect(MyAspect.class);
//proxyFactory.setProxyTargetClass(true);//是否需要使用CGLIB代理
HelloService proxy = proxyFactory.getProxy();
proxy.hello();
System.out.println(proxy.getClass()); //class com.sun.proxy.$Proxy6
}
输出:
-----------before-----------
this is my method~~
class com.sun.proxy.$Proxy6
这里面很有意思的地方在于:我们只是proxyFactory.addAspect(MyAspect.class);
,就自动帮我们完成了方法、通知的绑定工作。
注意:
- 需要注意的是在使用
AspectjProxyFactory
基于切面类创建代理对象时,我们指定的切面类上必须包含@Aspect
注解。 - 虽然我们自己通过编程的方式可以通过
AspectjProxyFactory
创建基于@Aspect
标注的切面类的代理,但是通过配置<aop:aspectj-autoproxy/>(@EnableAspectJAutoProxy)
使用基于注解的Aspectj
风格的Aop时,Spring内部不是通过AspectjProxyFactory创建的代理对象,而是通过ProxyFactory(这个在分析自动代理源码的时候有说到过~~~~)
5.5.2.6 ProxyFactory逻辑总结
AspectJProxyFactory,ProxyFactoryBean,ProxyFactory
大体逻辑都是:
- 填充
AdvisedSupport
(将代理对象target,注册的interceptorName,也就是advice增强名称,也就是将所有advice转换为advisor填充入advisedSupport),然后交给父类ProxyCreatorSupport
。 - 得到
JDK或者CGLIB的AopProxy
- 代理调用时候被invoke或者intercept方法拦截 (分别在
JdkDynamicAopProxy
和ObjenesisCglibAopProxy(CglibAopProxy的子类)
中) 并且在这两个方法中调用ProxyCreatorSupport
的getInterceptorsAndDynamicInterceptionAdvice
方法去初始化advice
和各个方法直接映射关系并缓存
该部分,是advised部分的整体逻辑。
5.5.3 ProxyProcessorSupport
为自动代理创建器AutoProxyCreator提供基础的方法,且其为proxyConfig配置类。
该类为proxy processor处理器提供基本功能,包括classloader的管理和evaluateProxyInterfaces方法,该方法判断class上的接口,如果接口interfaces,则设置到proxyfactory中;如果没有接口,设置proxyFactory.setProxyTargetClass(true),表示用cglib创建代理类。
public class ProxyProcessorSupport extends ProxyConfig implements Ordered, BeanClassLoaderAware, AopInfrastructureBean {
/**
* This should run after all other processors, so that it can just add
* an advisor to existing proxies rather than double-proxy.
* 【AOP的自动代理创建器必须在所有的别的processors之后执行,以确保它可以代理到所有的小伙伴们,即使需要双重代理得那种】
*/
private int order = Ordered.LOWEST_PRECEDENCE;
// 当然此处还是提供了方法,你可以自己set或者使用@Order来人为的改变这个顺序~~~
public void setOrder(int order) {
this.order = order;
}
@Override
public int getOrder() {
return this.order;
}
...
// 这是它提供的一个最为核心的方法:这里决定了如果目标类没有实现接口直接就是Cglib代理
// 检查给定beanClass上的接口们,并交给proxyFactory处理
protected void evaluateProxyInterfaces(Class<?> beanClass, ProxyFactory proxyFactory) {
// 找到该类实现的所有接口们~~~
Class<?>[] targetInterfaces = ClassUtils.getAllInterfacesForClass(beanClass, getProxyClassLoader());
// 标记:是否有存在【合理的】接口~~~
boolean hasReasonableProxyInterface = false;
for (Class<?> ifc : targetInterfaces) { //1
if (!isConfigurationCallbackInterface(ifc) && !isInternalLanguageInterface(ifc) &&
// 如果所实现的接口,有一个接口有方法,就标识为,当前代理类beanclass有合理的代理接口
ifc.getMethods().length > 0) { //2
hasReasonableProxyInterface = true;
break;
}//2
} //1
//如果被代理类有合理的class接口
if (hasReasonableProxyInterface) {
// Must allow for introductions; can't just set interfaces to the target's interfaces only.
// 这里Spring的Doc特别强调了:不能值只把合理的接口设置进去,而是都得加入进去
for (Class<?> ifc : targetInterfaces) {
proxyFactory.addInterface(ifc);
}
}
else {
// 这个很明显设置true,表示使用CGLIB得方式去创建代理了~~~~
proxyFactory.setProxyTargetClass(true);
}
}
// 判断此接口类型是否属于:容器去回调的类型,这里例举处理一些接口 初始化、销毁、自动刷新、自动关闭、Aware感知等等
protected boolean isConfigurationCallbackInterface(Class<?> ifc) {
return (InitializingBean.class == ifc || DisposableBean.class == ifc || Closeable.class == ifc ||
AutoCloseable.class == ifc || ObjectUtils.containsElement(ifc.getInterfaces(), Aware.class));
}
// 是否是如下通用的接口。若实现的是这些接口也会排除,不认为它是实现了接口的类
protected boolean isInternalLanguageInterface(Class<?> ifc) {
return (ifc.getName().equals("groovy.lang.GroovyObject") ||
ifc.getName().endsWith(".cglib.proxy.Factory") ||
ifc.getName().endsWith(".bytebuddy.MockAccess"));
}
}
类ProxyProcessorSupport作用,是对传入的beanClass和其proxyFactory参数,检查是否实现接口,如果有向proxyFactory设置接口;如果没有,设置代理模式为cglib。
5.5.3.1 AbstractAutoProxyCreator
该类是对自动代理创建器的抽象实现,并且实现了[InstantiationAwareBeanPostProcessor](#3.3.3.1.1 InstantiationAwareBeanPostProcessor)接口,所以该类会介入springIOC容器实例化bean的前后调用,如果有需要返回的proxy代理对象,则终止常规默认的实例化。且因为其是BeanPostProcessor,会在初始化的前后被调用。
这里重点提一个方法(如下图):在bean被create之前,先会执行所有的InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation
,谁第一个返回了不为null的Bean,后面就都不会执行了 。然后会再执行BeanPostProcessor#postProcessAfterInitialization
。
AbstractAutoProxyCreator作用:
整个Spring AOP模块的协作组件,它作为AOP的指挥官角色,统一协作Advisor(切面)和AopProxy(动态代理)这两大核心组件。它的本质是BeanPostProcessor(后置处理器)的一种实现,通过Spring IOC模块来启动运行。它针对的主体是Spring的Bean对象。

public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport
implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware {
protected Object createProxy(Class<?> beanClass, @Nullable String beanName,
@Nullable Object[] specificInterceptors, TargetSource targetSource) {
if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
}
//通过ProxyFactory实例,创建代理对象
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.copyFrom(this);
if (!proxyFactory.isProxyTargetClass()) {
if (shouldProxyTargetClass(beanClass, beanName)) {
proxyFactory.setProxyTargetClass(true);
}
else {
evaluateProxyInterfaces(beanClass, proxyFactory);
}
}
//构建advisor的chain链
Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
//设置proxyfactory的属性
//将advisors添加入proxyfactory内list<Advisor>
proxyFactory.addAdvisors(advisors);
proxyFactory.setTargetSource(targetSource);
customizeProxyFactory(proxyFactory);
proxyFactory.setFrozen(this.freezeProxy);
if (advisorsPreFiltered()) {
proxyFactory.setPreFiltered(true);
}
//AbstractAutoProxyCreator.createProxy---->proxyFactory.getProxy---->createAopProxy().getProxy
//上述调用链,创建AOP的代理类
return proxyFactory.getProxy(getProxyClassLoader());
}
通过createProxy,创建proxyfactory,来获取AopProxy代理对象。
完成以下任务:
-
通过扫描有@Aspect注解的类,构建候选的Advisor切面集合;
-
在Aspect注解类中循环查找没有@PointCut注解的方法封装成Advice对象(@Aspect注解的类是切面类,其中包括两部分:@PointCut标注的部分,为切点定义;非@PointCut的方法,对应的就是增强方法,需要封装成Advice);
-
通过方法上的注解找到对应的PointCut拦截目标,并把Advisor上的表达式封装到PointCut对象中;
-
然后结合当前的Bean对象的元数据,过滤找到有效的Advisor集合。
-
最后通过beanClass创建针对当前bean的动态代理对象;在代理对象执行方法时,拦截方法,动态运行Advisor调用链,完成对当前bean中匹配目标的拦截和增强。
5.5.3.2 区别ProxyCreatorSupport和AbstractAutoProxyCreator
两个类是ProxyConfig的两大实现类,前者是ProxyFactory的父类,用来手动创建代理对象;后者继承自InstantiationAwarePostProcessor,会在bean实例化和初始换的前后,被调用,而且,该类内部在创建代理类createProxy时,是通过创建ProxyFactory,并调用ProxyFactory.getProxy方法创建代理对象的。
5.5.3.3 AnnotationAwareAspectJAutoProxyCreator
InstantiationAwareBeanPostProcessor作为后置处理器对象,但是其作为InstantiationAware,额外提供了bean实例化Instantiation的before和after的处理方法,如下:
5.5.3.4 AopInfrastructureBean
ProxyProcessorSupport是AopInfrastructureBean的实现类。
实现该接口,表示该bean是一个springaop的基础类,该类不会被aop代理,不会产生aop的代理对象,即使该bean被advisor切面所切入。
5.5.4 AopProxyFactory
aopProxy的factory工厂类,负责创建aopProxy
public interface AopProxyFactory {
AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException;
}
5.5.4.1 DefaultAopProxyFactory
该类定义了createAopProxy的逻辑
//DefaultAopProxyFactory#createAopProxy
public class DefaultAopProxyFactory implements AopProxyFactory, Serializable {
@Override
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
// 需要对代理进行优化、代理的是目标类(强制cglib)、没有实现接口等都会进入这里面来
if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) { //1
Class<?> targetClass = config.getTargetClass();
if (targetClass == null) {
throw new AopConfigException("TargetSource cannot determine target class: " +
"Either an interface or a target is required for proxy creation.");
}
// 倘若目标Class本身就是个接口,或者它已经是个JDK得代理类(Proxy的子类。所有的JDK代理类都是此类的子类),仍旧用JDK的动态代理
if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
return new JdkDynamicAopProxy(config);
}
// 实用CGLIB代理方式 ObjenesisCglibAopProxy是CglibAopProxy的子类。Spring4.0之后提供的
return new ObjenesisCglibAopProxy(config);
} //1
// 否则(一般都是有实现接口) 都会采用JDK得动态代理
else {
return new JdkDynamicAopProxy(config);
}
}
// 如果它没有实现过接口(ifcs.length == ) 或者 仅仅实现了一个接口,但是呢这个接口却是SpringProxy类型的 那就返回false
// 总体来说,就是看看这个cofnig有没有实现过靠谱的、可以用的接口
// SpringProxy:一个标记接口。Spring AOP产生的所有的代理类 都是它的子类~~
private boolean hasNoUserSuppliedProxyInterfaces(AdvisedSupport config) {
Class<?>[] ifcs = config.getProxiedInterfaces();
return (ifcs.length == 0 || (ifcs.length == 1 && SpringProxy.class.isAssignableFrom(ifcs[0])));
}
}
创建AopProxy的逻辑流程:
5.5.4.2 AopProxy
AopProxy是独立的接口,不依赖于Proxy
AopProxy是springAOP中特殊的自用的类。有两个不同实现类,来创建代理对象。
public interface AopProxy {
Object getProxy();
Object getProxy(@Nullable ClassLoader classLoader);
}
动态代理的基接口,它扩展了JDK内置的动态代理能力和Cglib类代理能力;