Skip to content

Commit 5d48d73

Browse files
authored
Merge pull request code4craft#5 from yusijia/master
tiny-spring详细分析
2 parents 852d12a + 8bf3714 commit 5d48d73

File tree

67 files changed

+2112
-0
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

67 files changed

+2112
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package com.ysj.tinySpring;
2+
3+
/**
4+
* 用于代表property标签的ref属性里的对象
5+
*
6+
*/
7+
public class BeanReference {
8+
9+
public String name;
10+
11+
public Object bean;
12+
13+
public BeanReference(String name){
14+
this.name = name;
15+
}
16+
17+
18+
public String getName() {
19+
return name;
20+
}
21+
22+
public void setName(String name) {
23+
this.name = name;
24+
}
25+
26+
public Object getBean() {
27+
return bean;
28+
}
29+
30+
public void setBean(Object bean) {
31+
this.bean = bean;
32+
}
33+
34+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package com.ysj.tinySpring.aop;
2+
3+
/**
4+
* 继承了AopProxy接口,有获取代理对象的能力
5+
* 同时继承此接口有AdvisedSupport的支持
6+
*
7+
*/
8+
public abstract class AbstractAopProxy implements AopProxy{
9+
10+
protected AdvisedSupport advised;
11+
12+
public AbstractAopProxy(AdvisedSupport advised) {
13+
this.advised = advised;
14+
}
15+
16+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
package com.ysj.tinySpring.aop;
2+
3+
import org.aopalliance.intercept.MethodInterceptor;
4+
5+
/**
6+
* AdvisedSupport封装了TargetSource, MethodInterceptor和MethodMatcher
7+
*
8+
*/
9+
public class AdvisedSupport {
10+
11+
// 要拦截的对象
12+
private TargetSource targetSource;
13+
14+
/**
15+
* 方法拦截器
16+
* Spring的AOP只支持方法级别的调用,所以其实在AopProxy里,我们只需要将MethodInterceptor放入对象的方法调用
17+
*/
18+
private MethodInterceptor methodInterceptor;
19+
20+
// 方法匹配器,判断是否是需要拦截的方法
21+
private MethodMatcher methodMatcher;
22+
23+
24+
25+
public TargetSource getTargetSource() {
26+
return targetSource;
27+
}
28+
29+
public void setTargetSource(TargetSource targetSource) {
30+
this.targetSource = targetSource;
31+
}
32+
33+
public MethodInterceptor getMethodInterceptor() {
34+
return methodInterceptor;
35+
}
36+
37+
public void setMethodInterceptor(MethodInterceptor methodInterceptor) {
38+
this.methodInterceptor = methodInterceptor;
39+
}
40+
41+
public MethodMatcher getMethodMatcher() {
42+
return methodMatcher;
43+
}
44+
45+
public void setMethodMatcher(MethodMatcher methodMatcher) {
46+
this.methodMatcher = methodMatcher;
47+
}
48+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package com.ysj.tinySpring.aop;
2+
3+
import org.aopalliance.aop.Advice;
4+
5+
/**
6+
* 通知器
7+
* 用于实现 具体的方法拦截,需要使用者编写,也就对应了 Spring 中的前置通知、后置通知、环切通知等。
8+
*
9+
*/
10+
public interface Advisor {
11+
12+
/**
13+
* 获取通知器(方法拦截器)
14+
* @return
15+
*/
16+
Advice getAdvice();
17+
18+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package com.ysj.tinySpring.aop;
2+
3+
/**
4+
* AopProxy是个标志型接口
5+
* 暴露获取aop代理对象方法的接口
6+
*
7+
*/
8+
public interface AopProxy {
9+
10+
/**
11+
* 获取代理对象
12+
* @return
13+
*/
14+
Object getProxy();
15+
16+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
package com.ysj.tinySpring.aop;
2+
3+
import java.lang.reflect.Method;
4+
5+
import org.aopalliance.aop.Advice;
6+
import org.aopalliance.intercept.MethodInterceptor;
7+
import org.aopalliance.intercept.MethodInvocation;
8+
9+
import com.ysj.tinySpring.beans.factory.BeanFactory;
10+
11+
/**
12+
* 环绕通知
13+
* 用AspectJ表达式匹配
14+
*
15+
*/
16+
public class AspectJAroundAdvice implements Advice, MethodInterceptor {
17+
18+
private BeanFactory beanFactory;
19+
20+
private Method aspectJAdviceMethod;
21+
22+
private String aspectInstanceName;
23+
24+
@Override
25+
public Object invoke(MethodInvocation invocation) throws Throwable {
26+
return aspectJAdviceMethod.invoke(beanFactory.getBean(aspectInstanceName), invocation);
27+
}
28+
29+
public BeanFactory getBeanFactory() {
30+
return beanFactory;
31+
}
32+
33+
public void setBeanFactory(BeanFactory beanFactory) {
34+
this.beanFactory = beanFactory;
35+
}
36+
37+
public Method getAspectJAdviceMethod() {
38+
return aspectJAdviceMethod;
39+
}
40+
41+
public void setAspectJAdviceMethod(Method aspectJAdviceMethod) {
42+
this.aspectJAdviceMethod = aspectJAdviceMethod;
43+
}
44+
45+
public String getAspectInstanceName() {
46+
return aspectInstanceName;
47+
}
48+
49+
public void setAspectInstanceName(String aspectInstanceName) {
50+
this.aspectInstanceName = aspectInstanceName;
51+
}
52+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
package com.ysj.tinySpring.aop;
2+
3+
import java.util.List;
4+
5+
import org.aopalliance.intercept.MethodInterceptor;
6+
7+
import com.ysj.tinySpring.beans.BeanPostProcessor;
8+
import com.ysj.tinySpring.beans.factory.AbstractBeanFactory;
9+
import com.ysj.tinySpring.beans.factory.BeanFactory;
10+
11+
/**
12+
* 实现了BeanFactoryAware接口:这个接口提供了对 BeanFactory 的感知,这样,尽管它是容器中的一个 Bean,却
13+
* 可以获取容器 的引用,进而获取容器中所有的切点对象,决定对哪些对象的哪些方法进行代理。解决了 为哪些对象
14+
* 提供 AOP 的植入 的问题。
15+
*
16+
*/
17+
public class AspectJAwareAdvisorAutoProxyCreator implements BeanPostProcessor, BeanFactoryAware {
18+
19+
private AbstractBeanFactory beanFactory;
20+
21+
@Override
22+
public Object postProcessBeforeInitialization(Object bean, String beanName) throws Exception {
23+
return bean;
24+
}
25+
26+
/**
27+
* 可以取看看AbstractBeanFactory的getBean()的实现
28+
* bean实例化后要进行初始化操作,会经过这个方法满足条件则生成相关的代理类并返回
29+
*/
30+
@Override
31+
public Object postProcessAfterInitialization(Object bean, String beanName) throws Exception {
32+
// 如果是切点通知器,则直接返回
33+
if (bean instanceof AspectJExpressionPointcutAdvisor) {
34+
return bean;
35+
}
36+
// 如果bean是方法拦截器,则直接返回
37+
if (bean instanceof MethodInterceptor) {
38+
return bean;
39+
}
40+
// 通过getBeansForType方法加载BeanFactory 中所有的 PointcutAdvisor(保证了 PointcutAdvisor 的实例化顺序优于普通 Bean。)
41+
// AspectJ方式实现织入,这里它会扫描所有Pointcut,并对bean做织入。
42+
List<AspectJExpressionPointcutAdvisor> advisors = beanFactory
43+
.getBeansForType(AspectJExpressionPointcutAdvisor.class);
44+
for (AspectJExpressionPointcutAdvisor advisor : advisors) {
45+
// 匹配要拦截的类
46+
// 使用AspectJExpressionPointcut的matches匹配器,判断当前对象是不是要拦截的类的对象。
47+
if (advisor.getPointcut().getClassFilter().matches(bean.getClass())) {
48+
// ProxyFactory继承了AdvisedSupport,所以内部封装了TargetSource和MethodInterceptor的元数据对象
49+
ProxyFactory advisedSupport = new ProxyFactory();
50+
// 设置切点的方法拦截器
51+
advisedSupport.setMethodInterceptor((MethodInterceptor) advisor.getAdvice());
52+
// 设置切点的方法匹配器
53+
// 利用AspectJ表达式进行方法匹配
54+
// AspectJExpressionPointcutAdvisor里的AspectJExpressionPointcut的getMethodMatcher()方法
55+
advisedSupport.setMethodMatcher(advisor.getPointcut().getMethodMatcher());
56+
// 是要拦截的类, 生成一个 TargetSource(要拦截的对象和其类型)(被代理对象)
57+
TargetSource targetSource = new TargetSource(bean, bean.getClass(), bean.getClass().getInterfaces());
58+
advisedSupport.setTargetSource(targetSource);
59+
// 交给实现了 AopProxy接口的getProxy方法的ProxyFactory去生成代理对象
60+
return advisedSupport.getProxy();
61+
}
62+
}
63+
return bean;
64+
}
65+
66+
@Override
67+
public void setBeanFactory(BeanFactory beanFactory) throws Exception {
68+
this.beanFactory = (AbstractBeanFactory) beanFactory;
69+
}
70+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
package com.ysj.tinySpring.aop;
2+
3+
import java.lang.reflect.Method;
4+
import java.util.HashSet;
5+
import java.util.Set;
6+
7+
import org.aspectj.weaver.tools.PointcutExpression;
8+
import org.aspectj.weaver.tools.PointcutParser;
9+
import org.aspectj.weaver.tools.PointcutPrimitive;
10+
import org.aspectj.weaver.tools.ShadowMatch;
11+
12+
/**
13+
* 通过AspectJ表达式识别切点
14+
*
15+
*/
16+
public class AspectJExpressionPointcut implements Pointcut, ClassFilter, MethodMatcher {
17+
18+
private PointcutParser pointcutParser;
19+
20+
private String expression;
21+
22+
private PointcutExpression pointcutExpression;
23+
24+
private static final Set<PointcutPrimitive> DEFAULT_SUPPORTED_PRIMITIVES = new HashSet<PointcutPrimitive>();
25+
26+
static {
27+
DEFAULT_SUPPORTED_PRIMITIVES.add(PointcutPrimitive.EXECUTION);
28+
DEFAULT_SUPPORTED_PRIMITIVES.add(PointcutPrimitive.ARGS);
29+
DEFAULT_SUPPORTED_PRIMITIVES.add(PointcutPrimitive.REFERENCE);
30+
DEFAULT_SUPPORTED_PRIMITIVES.add(PointcutPrimitive.THIS);
31+
DEFAULT_SUPPORTED_PRIMITIVES.add(PointcutPrimitive.TARGET);
32+
DEFAULT_SUPPORTED_PRIMITIVES.add(PointcutPrimitive.WITHIN);
33+
DEFAULT_SUPPORTED_PRIMITIVES.add(PointcutPrimitive.AT_ANNOTATION);
34+
DEFAULT_SUPPORTED_PRIMITIVES.add(PointcutPrimitive.AT_WITHIN);
35+
DEFAULT_SUPPORTED_PRIMITIVES.add(PointcutPrimitive.AT_ARGS);
36+
DEFAULT_SUPPORTED_PRIMITIVES.add(PointcutPrimitive.AT_TARGET);
37+
}
38+
39+
public AspectJExpressionPointcut() {
40+
this(DEFAULT_SUPPORTED_PRIMITIVES);
41+
}
42+
43+
public AspectJExpressionPointcut(Set<PointcutPrimitive> supportedPrimitives) {
44+
pointcutParser = PointcutParser
45+
.getPointcutParserSupportingSpecifiedPrimitivesAndUsingContextClassloaderForResolution(supportedPrimitives);
46+
}
47+
48+
protected void checkReadyToMatch() {
49+
if (pointcutExpression == null) {
50+
pointcutExpression = buildPointcutExpression();
51+
}
52+
}
53+
54+
private PointcutExpression buildPointcutExpression() {
55+
return pointcutParser.parsePointcutExpression(expression);
56+
}
57+
58+
public void setExpression(String expression) {
59+
this.expression = expression;
60+
}
61+
62+
@Override
63+
public ClassFilter getClassFilter() {
64+
return this;
65+
}
66+
67+
@Override
68+
public MethodMatcher getMethodMatcher() {
69+
return this;
70+
}
71+
72+
@Override
73+
public boolean matches(Class targetClass) {
74+
checkReadyToMatch();
75+
return pointcutExpression.couldMatchJoinPointsInType(targetClass);
76+
}
77+
78+
@Override
79+
public boolean matches(Method method, Class targetClass) {
80+
checkReadyToMatch();
81+
ShadowMatch shadowMatch = pointcutExpression.matchesMethodExecution(method);
82+
if (shadowMatch.alwaysMatches()) {
83+
return true;
84+
} else if (shadowMatch.neverMatches()) {
85+
return false;
86+
}
87+
// TODO:其他情况不判断了!见org.springframework.aop.aspectj.RuntimeTestWalker
88+
return false;
89+
}
90+
91+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
package com.ysj.tinySpring.aop;
2+
3+
import org.aopalliance.aop.Advice;
4+
5+
/**
6+
* AspectJ表达式切点通知器
7+
*
8+
*/
9+
public class AspectJExpressionPointcutAdvisor implements PointcutAdvisor {
10+
11+
/**
12+
* AspectJ表达式切点匹配器
13+
* AspectJ表达式匹配的切点,默认有初始化。也默认有了MethodMatcher(AspectJExpressionPointcut实现了MethodMatcher接口)
14+
*/
15+
private AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
16+
17+
/**
18+
* 方法拦截器
19+
* 这个要用户自己去xml文件里配置方法拦截器(MethodInterceptor继承了Advice接口),
20+
* 在AspectJAwareAdvisorAutoProxyCreator设置代理对象的方法拦截器时将Advispr强转为MethodInterceptor
21+
*/
22+
private Advice advice;
23+
24+
public void setAdvice(Advice advice) {
25+
this.advice = advice;
26+
}
27+
28+
public void setExpression(String expression) {
29+
this.pointcut.setExpression(expression);
30+
}
31+
32+
@Override
33+
public Advice getAdvice() {
34+
return advice;
35+
}
36+
37+
@Override
38+
public Pointcut getPointcut() {
39+
return pointcut;
40+
}
41+
42+
}

0 commit comments

Comments
 (0)