// 获取和被代理类所匹配的Advisor
Callback[] callbacks = getCallbacks(rootClass);
Class[] types = new Class[callbacks.length];
for (int x = 0; x < types.length; x++) {
types[x] = callbacks[x].getClass();
}
// fixedInterceptorMap only populated at this point, after getCallbacks call above
enhancer.setCallbackFilter(new ProxyCallbackFilter(
this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));
enhancer.setCallbackTypes(types);
// Generate the proxy class and create a proxy instance.
return createProxyClassAndInstance(enhancer, callbacks);
@Override
@Nullable
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object oldProxy = null;
boolean setProxyContext = false;
// 拿到被代理对象
TargetSource targetSource = this.advised.targetSource;
Object target = null;
try {
// 如果接口中没有定义equals()方法,那么则直接调用,不走代理
if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
// The target does not implement the equals(Object) method itself.
return equals(args[0]);
}
// 同上
else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
// The target does not implement the hashCode() method itself.
return hashCode();
}
//没用过 留作以后再说
else if (method.getDeclaringClass() == DecoratingProxy.class) {
// There is only getDecoratedClass() declared -> dispatch to proxy config.
// 得到代理对象的类型,而不是所实现的接口
return AopProxyUtils.ultimateTargetClass(this.advised);
}
else if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&
method.getDeclaringClass().isAssignableFrom(Advised.class)) {
// 如果 方法所在的类是接口 并且是Advised的子类,则直接调用下面的方法,这个方法在下面分析
// Service invocations on ProxyConfig with the proxy config...
// 也是直接调用Advised接口中的方法,不走代理逻辑
// 其实就是利用代理对象获取ProxyFactory中的信息
return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
}
Object retVal;
//是否对外暴露代理对象
// 如果ProxyFactory的exposeProxy为true,则将代理对象设置到currentProxy这个ThreadLocal中去
if (this.advised.exposeProxy) {
// Make invocation available if necessary.
oldProxy = AopContext.setCurrentProxy(proxy);
setProxyContext = true;
}
// Get as late as possible to minimize the time we "own" the target,
// in case it comes from a pool.
// 被代理对象和代理类
target = targetSource.getTarget();
Class targetClass = (target != null ? target.getClass() : null);
// Get the interception chain for this method.
// 从Advised中根据方法名和目标类获取 AOP拦截器执行链 重点要分析的内容
// 代理对象在执行某个方法时,根据方法筛选出匹配的Advisor,并适配成Interceptor
// 代理对象在执行某个方法时,会把ProxyFactory中的Advisor拿出来和当前正在执行的方法进行匹配筛选
// 把和方法所匹配的Advisor适配成MethodInterceptor
List
@Override
@Nullable
public Object proceed() throws Throwable {
// We start with an index of -1 and increment early.
// currentInterceptorIndex初始值为-1,每调用一个interceptor就会加1
// 当调用完了最后一个interceptor后就会执行被代理方法
if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
// 下面会分析
return invokeJoinpoint();
}
// 获取集合中的 MethodInterceptor
Object interceptorOrInterceptionAdvice =
this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
// 当前interceptor是InterceptorAndDynamicMethodMatcher,则先进行匹配,匹配成功后再调用该interceptor
// 如果没有匹配则递归调用proceed()方法,调用下一个interceptor
if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
// Evaluate dynamic method matcher here: static part will already have
// been evaluated and found to match.
InterceptorAndDynamicMethodMatcher dm =
(InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
Class targetClass = (this.targetClass != null ? this.targetClass : this.method.getDeclaringClass());
// 这里每一次都去匹配是否适用于这个目标方法
if (dm.methodMatcher.matches(this.method, targetClass, this.arguments)) {
// 如果匹配则直接调用 MethodInterceptor的invoke方法
// 注意这里传入的参数是this 我们下面看一下 ReflectiveMethodInvocation的类型
return dm.interceptor.invoke(this);
}
else {
// Dynamic matching failed.
// Skip this interceptor and invoke the next in the chain.
// 如果不适用于此目标方法 则继续执行下一个链条
// 递归调用
return proceed();
}
}
else {
// It's an interceptor, so we just invoke it: The pointcut will have
// been evaluated statically before this object was constructed.
// 直接调用MethodInterceptor,传入this,在内部会再次调用proceed()方法进行递归
// 比如MethodBeforeAdviceInterceptor
return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
}
}
class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
/**
* Register, escalate, and configure the AspectJ auto proxy creator based on the value
* of the @{@link EnableAspectJAutoProxy#proxyTargetClass()} attribute on the importing
* {@code @Configuration} class.
*/
@Override
public void registerBeanDefinitions(
AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
// 注册一个AnnotationAwareAspectJAutoProxyCreator类型的Bean,beanName为AUTO_PROXY_CREATOR_BEAN_NAME
AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
// 修改AnnotationAwareAspectJAutoProxyCreator中对应的属性
AnnotationAttributes enableAspectJAutoProxy =
AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
if (enableAspectJAutoProxy != null) {
if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
}
if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
}
}
}
}
protected ListfindCandidateAdvisors() {
// Add all the Spring advisors found according to superclass rules.// 先调用父类的findCandidateAdvisors方法// 先找到所有Advisor类型的Bean对象
List advisors = super.findCandidateAdvisors();
// Build Advisors for all AspectJ aspects in the bean factory.// 再从所有切面中解析得到Advisor对象if (this.aspectJAdvisorsBuilder != null) {
advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
}
return advisors;
}
// 本方法会被多次调用,因为一个Bean在判断要不要进行AOP时,都会调用这个方法public ListbuildAspectJAdvisors() {
// aspectBeanNames是用来缓存BeanFactory中所存在的切面beanName的,第一次为null,后面就不为null了,不为null表示之前就已经找到过BeanFactory中的切面了
List aspectNames = this.aspectBeanNames;
if (aspectNames == null) {
synchronized (this) {
aspectNames = this.aspectBeanNames;
if (aspectNames == null) {
List advisors = newArrayList<>();
aspectNames = newArrayList<>();
// 把所有beanNames拿出来遍历,判断某个bean的类型是否是Aspect
String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
this.beanFactory, Object.class, true, false);
for (String beanName : beanNames) {
if (!isEligibleBean(beanName)) {
continue;
}
// We must be careful not to instantiate beans eagerly as in this case they// would be cached by the Spring container but would not have been weaved.// 注意看上面这个注释的内容:在这个场景下我们获取BeanClass的时候必须要小心处理,以免会提前初始化// Bean,这些Bean在初始化之后会被Spring容器缓存起来,但是这些Bean可能还没有被织入。
Class beanType = this.beanFactory.getType(beanName, false);
if (beanType == null) {
continue;
}
// 判断上面获取到的BeanClass是否带有Aspect注解if (this.advisorFactory.isAspect(beanType)) {
aspectNames.add(beanName);
//创建切面元数据 //参考: https://blog.csdn.net/zknxx/article/details/79685290AspectMetadataamd=newAspectMetadata(beanType, beanName);
// 如果@Aspect不是perthis、pertarget,那么一个切面只会生成一个对象(单例)// 并且会将该切面中所对应的Advisor对象进行缓存if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {
MetadataAwareAspectInstanceFactoryfactory=newBeanFactoryAspectInstanceFactory(this.beanFactory, beanName);
// 利用BeanFactoryAspectInstanceFactory来解析Aspect类
List classAdvisors = this.advisorFactory.getAdvisors(factory);
if (this.beanFactory.isSingleton(beanName)) {
// 缓存切面所对应的所有Advisor对象this.advisorsCache.put(beanName, classAdvisors);
}
else {
this.aspectFactoryCache.put(beanName, factory);
}
advisors.addAll(classAdvisors);
}
else {
// Per target or per this.if (this.beanFactory.isSingleton(beanName)) {
thrownewIllegalArgumentException("Bean with name '" + beanName +
"' is a singleton, but aspect instantiation model is not singleton");
}
MetadataAwareAspectInstanceFactoryfactory=newPrototypeAspectInstanceFactory(this.beanFactory, beanName);
this.aspectFactoryCache.put(beanName, factory);
// 利用PrototypeAspectInstanceFactory来解析Aspect类// PrototypeAspectInstanceFactory的父类为BeanFactoryAspectInstanceFactory// 这两个Factory的区别在于PrototypeAspectInstanceFactory的构造方法中会判断切面Bean是不是原型,除此之外没有其他区别// 所以主要就是BeanFactoryAspectInstanceFactory来负责生成切面实例对象
advisors.addAll(this.advisorFactory.getAdvisors(factory));
}
}
}
this.aspectBeanNames = aspectNames;
return advisors;
}
}
}
if (aspectNames.isEmpty()) {
return Collections.emptyList();
}
// 如果切面已经找到过了,那么则遍历每个切面是否缓存了对应的Advisor,如果没有缓存则进行解析得到Advisor
List advisors = newArrayList<>();
for (String aspectName : aspectNames) {
List cachedAdvisors = this.advisorsCache.get(aspectName);
if (cachedAdvisors != null) {
advisors.addAll(cachedAdvisors);
}
else {
MetadataAwareAspectInstanceFactoryfactory=this.aspectFactoryCache.get(aspectName);
advisors.addAll(this.advisorFactory.getAdvisors(factory));
}
}
return advisors;
}
以上是获取Spring容器中的所有的通知方法 封装为Advisor集合
最后我们再看看目标对象的创建过程:
// specificInterceptors 上面的方法中获取到的Advisor// targetSource 为 new SingletonTargetSource(bean)// 将Spring容器中创建出来的bean封装为了SingletonTargetSourceprotected Object createProxy(Class beanClass, @Nullable String beanName,
@Nullable Object[] specificInterceptors, TargetSource targetSource) {
// 这里将目标Bean的Class设置为BeanDefinition中的一个属性// 在使用JDK动态代理的时候 可能会用到这个属性 https://stackoverflow.com/questions/45463757/what-is-interface-based-proxyingif (this.beanFactory instanceof ConfigurableListableBeanFactory) {
AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
}
// 这里创建了一个新的 ProxyFactoryProxyFactoryproxyFactory=newProxyFactory();
proxyFactory.copyFrom(this);
// 这里是 判断是否强制使用 cglibif (proxyFactory.isProxyTargetClass()) {
// Explicit handling of JDK proxy targets (for introduction advice scenarios)// 这里 判断是 使用jdk动态代理 还是cglib代理if (Proxy.isProxyClass(beanClass)) {
// Must allow for introductions; can't just set interfaces to the proxy's interfaces only.for (Class ifc : beanClass.getInterfaces()) {
proxyFactory.addInterface(ifc);
}
}
}
else {
// No proxyTargetClass flag enforced, let's apply our default checks...if (shouldProxyTargetClass(beanClass, beanName)) {
proxyFactory.setProxyTargetClass(true);
}
else {
evaluateProxyInterfaces(beanClass, proxyFactory);
}
}
// 如果使用了@DeclareParents,那么在添加advisor时,会把对应的接口添加到ProxyFactory中// 在这一步会去判断advisors中是否存在IntroductionAdvisor,如果存在会把对应的Interface添加到ProxyFactory中
Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
proxyFactory.addAdvisors(advisors);
// targetSource 里是包含目标对象的
proxyFactory.setTargetSource(targetSource);
customizeProxyFactory(proxyFactory);
proxyFactory.setFrozen(this.freezeProxy);
if (advisorsPreFiltered()) {
proxyFactory.setPreFiltered(true);
}
// Use original ClassLoader if bean class not locally loaded in overriding class loaderClassLoaderclassLoader= getProxyClassLoader();
if (classLoader instanceof SmartClassLoader && classLoader != beanClass.getClassLoader()) {
classLoader = ((SmartClassLoader) classLoader).getOriginalClassLoader();
}
// 创建代理对象 关于创建代理对象的分析 上面分析过了return proxyFactory.getProxy(classLoader);
}
参考:http://blog.csdn.net/qingfeilee/article/details/7052736
org.hibernate.NonUniqueResultException: query did not return a unique result: 2
在项目中出现了org.hiber
由Oracle通信技术部门主导的演示项目并没有在本月较早前法国南斯举行的行业集团TM论坛大会中获得嘉奖。但是,Oracle通信官员解雇致力于打造一个支持零干预分配和编制功能的网络即服务(NaaS)平台,帮助企业以更灵活和更适合云的方式实现通信服务提供商(CSP)的连接产品。这个Oracle主导的项目属于TM Forum Live!活动上展示的Catalyst计划的19个项目之一。Catalyst计
Spring MVC提供了非常方便的文件上传功能。
1,配置Spring支持文件上传:
DispatcherServlet本身并不知道如何处理multipart的表单数据,需要一个multipart解析器把POST请求的multipart数据中抽取出来,这样DispatcherServlet就能将其传递给我们的控制器了。为了在Spring中注册multipart解析器,需要声明一个实现了Mul
the CollabNet user information center http://help.collab.net/
How do I create a new Wiki page?
A CollabNet TeamForge project can have any number of Wiki pages. All Wiki pages are linked, and
package beautyOfCoding;
import java.util.Arrays;
import java.util.Random;
public class MaxSubArraySum2 {
/**
* 编程之美 子数组之和的最大值(二维)
*/
private static final int ROW = 5;
private stat
示例程序,swap_1和swap_2都是错误的,推理从1开始推到2,2没完成,推到3就完成了
# include <stdio.h>
void swap_1(int, int);
void swap_2(int *, int *);
void swap_3(int *, int *);
int main(void)
{
int a = 3;
int b =
同步工具类包括信号量(Semaphore)、栅栏(barrier)、闭锁(CountDownLatch)
闭锁(CountDownLatch)
public class RunMain {
public long timeTasks(int nThreads, final Runnable task) throws InterruptedException {
fin
不止一次,看到很多讲技术的文章里面出现过这个词语。今天终于弄懂了——通过朋友给的浏览软件,上了wiki。
我再一次感到,没有辞典能像WiKi一样,给出这样体贴人心、一清二楚的解释了。为了表达我对WiKi的喜爱,只好在此一一中英对照,给大家上次课。
In computer science, bleeding edge is a term that