Skip to content

Commit 905e037

Browse files
committed
invite-cglib-and-aopproxy-factory
1 parent e7ad47f commit 905e037

12 files changed

+174
-28
lines changed

pom.xml

+5
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,11 @@
4545
<artifactId>aspectjweaver</artifactId>
4646
<version>1.6.11</version>
4747
</dependency>
48+
<dependency>
49+
<groupId>cglib</groupId>
50+
<artifactId>cglib-nodep</artifactId>
51+
<version>2.1_3</version>
52+
</dependency>
4853
</dependencies>
4954

5055
<build>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package us.codecraft.tinyioc.aop;
2+
3+
/**
4+
5+
*/
6+
public abstract class AbstractAopProxy implements AopProxy {
7+
8+
protected AdvisedSupport advised;
9+
10+
public AbstractAopProxy(AdvisedSupport advised) {
11+
this.advised = advised;
12+
}
13+
}

src/main/java/us/codecraft/tinyioc/aop/AspectJAwareAdvisorAutoProxyCreator.java

+6-6
Original file line numberDiff line numberDiff line change
@@ -24,21 +24,21 @@ public Object postProcessAfterInitialization(Object bean, String beanName) throw
2424
if (bean instanceof AspectJExpressionPointcutAdvisor) {
2525
return bean;
2626
}
27-
if (bean instanceof MethodInterceptor) {
28-
return bean;
29-
}
27+
if (bean instanceof MethodInterceptor) {
28+
return bean;
29+
}
3030
List<AspectJExpressionPointcutAdvisor> advisors = beanFactory
3131
.getBeansForType(AspectJExpressionPointcutAdvisor.class);
3232
for (AspectJExpressionPointcutAdvisor advisor : advisors) {
3333
if (advisor.getPointcut().getClassFilter().matches(bean.getClass())) {
34-
AdvisedSupport advisedSupport = new AdvisedSupport();
34+
ProxyFactory advisedSupport = new ProxyFactory();
3535
advisedSupport.setMethodInterceptor((MethodInterceptor) advisor.getAdvice());
3636
advisedSupport.setMethodMatcher(advisor.getPointcut().getMethodMatcher());
3737

38-
TargetSource targetSource = new TargetSource(bean, bean.getClass().getInterfaces());
38+
TargetSource targetSource = new TargetSource(bean, bean.getClass(), bean.getClass().getInterfaces());
3939
advisedSupport.setTargetSource(targetSource);
4040

41-
return new JdkDynamicAopProxy(advisedSupport).getProxy();
41+
return advisedSupport.getProxy();
4242
}
4343
}
4444
return bean;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
package us.codecraft.tinyioc.aop;
2+
3+
import net.sf.cglib.proxy.Enhancer;
4+
import net.sf.cglib.proxy.MethodInterceptor;
5+
import net.sf.cglib.proxy.MethodProxy;
6+
7+
import java.lang.reflect.Method;
8+
9+
/**
10+
11+
*/
12+
public class Cglib2AopProxy extends AbstractAopProxy {
13+
14+
public Cglib2AopProxy(AdvisedSupport advised) {
15+
super(advised);
16+
}
17+
18+
@Override
19+
public Object getProxy() {
20+
Enhancer enhancer = new Enhancer();
21+
enhancer.setSuperclass(advised.getTargetSource().getTargetClass());
22+
enhancer.setInterfaces(advised.getTargetSource().getInterfaces());
23+
enhancer.setCallback(new DynamicAdvisedInterceptor(advised));
24+
Object enhanced = enhancer.create();
25+
return enhanced;
26+
}
27+
28+
private static class DynamicAdvisedInterceptor implements MethodInterceptor {
29+
30+
private AdvisedSupport advised;
31+
32+
private org.aopalliance.intercept.MethodInterceptor delegateMethodInterceptor;
33+
34+
private DynamicAdvisedInterceptor(AdvisedSupport advised) {
35+
this.advised = advised;
36+
this.delegateMethodInterceptor = advised.getMethodInterceptor();
37+
}
38+
39+
@Override
40+
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
41+
if (advised.getMethodMatcher() == null
42+
|| advised.getMethodMatcher().matches(method, advised.getTargetSource().getTargetClass())) {
43+
return delegateMethodInterceptor.invoke(new CglibMethodInvocation(advised.getTargetSource().getTarget(), method, args, proxy));
44+
}
45+
return new CglibMethodInvocation(advised.getTargetSource().getTarget(), method, args, proxy).proceed();
46+
}
47+
}
48+
49+
private static class CglibMethodInvocation extends ReflectiveMethodInvocation {
50+
51+
private final MethodProxy methodProxy;
52+
53+
public CglibMethodInvocation(Object target, Method method, Object[] args, MethodProxy methodProxy) {
54+
super(target, method, args);
55+
this.methodProxy = methodProxy;
56+
}
57+
58+
@Override
59+
public Object proceed() throws Throwable {
60+
return this.methodProxy.invoke(this.target, this.arguments);
61+
}
62+
}
63+
64+
}

src/main/java/us/codecraft/tinyioc/aop/JdkDynamicAopProxy.java

+5-7
Original file line numberDiff line numberDiff line change
@@ -11,17 +11,15 @@
1111
*
1212
1313
*/
14-
public class JdkDynamicAopProxy implements AopProxy, InvocationHandler {
14+
public class JdkDynamicAopProxy extends AbstractAopProxy implements InvocationHandler {
1515

16-
private AdvisedSupport advised;
17-
18-
public JdkDynamicAopProxy(AdvisedSupport advised) {
19-
this.advised = advised;
20-
}
16+
public JdkDynamicAopProxy(AdvisedSupport advised) {
17+
super(advised);
18+
}
2119

2220
@Override
2321
public Object getProxy() {
24-
return Proxy.newProxyInstance(getClass().getClassLoader(), advised.getTargetSource().getTargetClass(), this);
22+
return Proxy.newProxyInstance(getClass().getClassLoader(), advised.getTargetSource().getInterfaces(), this);
2523
}
2624

2725
@Override
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package us.codecraft.tinyioc.aop;
2+
3+
/**
4+
5+
*/
6+
public class ProxyFactory extends AdvisedSupport implements AopProxy {
7+
8+
@Override
9+
public Object getProxy() {
10+
return createAopProxy().getProxy();
11+
}
12+
13+
protected final AopProxy createAopProxy() {
14+
return new Cglib2AopProxy(this);
15+
}
16+
}

src/main/java/us/codecraft/tinyioc/aop/ReflectiveMethodInvocation.java

+7-7
Original file line numberDiff line numberDiff line change
@@ -10,16 +10,16 @@
1010
*/
1111
public class ReflectiveMethodInvocation implements MethodInvocation {
1212

13-
private Object target;
13+
protected Object target;
1414

15-
private Method method;
15+
protected Method method;
1616

17-
private Object[] args;
17+
protected Object[] arguments;
1818

19-
public ReflectiveMethodInvocation(Object target, Method method, Object[] args) {
19+
public ReflectiveMethodInvocation(Object target, Method method, Object[] arguments) {
2020
this.target = target;
2121
this.method = method;
22-
this.args = args;
22+
this.arguments = arguments;
2323
}
2424

2525
@Override
@@ -29,12 +29,12 @@ public Method getMethod() {
2929

3030
@Override
3131
public Object[] getArguments() {
32-
return args;
32+
return arguments;
3333
}
3434

3535
@Override
3636
public Object proceed() throws Throwable {
37-
return method.invoke(target, args);
37+
return method.invoke(target, arguments);
3838
}
3939

4040
@Override

src/main/java/us/codecraft/tinyioc/aop/TargetSource.java

+10-3
Original file line numberDiff line numberDiff line change
@@ -6,20 +6,27 @@
66
*/
77
public class TargetSource {
88

9-
private Class<?>[] targetClass;
9+
private Class<?> targetClass;
10+
11+
private Class<?>[] interfaces;
1012

1113
private Object target;
1214

13-
public TargetSource(Object target, Class<?>... targetClass) {
15+
public TargetSource(Object target, Class<?> targetClass,Class<?>... interfaces) {
1416
this.target = target;
1517
this.targetClass = targetClass;
18+
this.interfaces = interfaces;
1619
}
1720

18-
public Class<?>[] getTargetClass() {
21+
public Class<?> getTargetClass() {
1922
return targetClass;
2023
}
2124

2225
public Object getTarget() {
2326
return target;
2427
}
28+
29+
public Class<?>[] getInterfaces() {
30+
return interfaces;
31+
}
2532
}

src/main/java/us/codecraft/tinyioc/beans/factory/AbstractBeanFactory.java

+1
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ public Object getBean(String name) throws Exception {
3030
if (bean == null) {
3131
bean = doCreateBean(beanDefinition);
3232
bean = initializeBean(bean, name);
33+
beanDefinition.setBean(bean);
3334
}
3435
return bean;
3536
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
package us.codecraft.tinyioc.aop;
2+
3+
import org.junit.Test;
4+
import us.codecraft.tinyioc.HelloWorldService;
5+
import us.codecraft.tinyioc.HelloWorldServiceImpl;
6+
import us.codecraft.tinyioc.context.ApplicationContext;
7+
import us.codecraft.tinyioc.context.ClassPathXmlApplicationContext;
8+
9+
/**
10+
11+
*/
12+
public class Cglib2AopProxyTest {
13+
14+
@Test
15+
public void testInterceptor() throws Exception {
16+
// --------- helloWorldService without AOP
17+
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("tinyioc.xml");
18+
HelloWorldService helloWorldService = (HelloWorldService) applicationContext.getBean("helloWorldService");
19+
helloWorldService.helloWorld();
20+
21+
// --------- helloWorldService with AOP
22+
// 1. 设置被代理对象(Joinpoint)
23+
AdvisedSupport advisedSupport = new AdvisedSupport();
24+
TargetSource targetSource = new TargetSource(helloWorldService, HelloWorldServiceImpl.class,
25+
HelloWorldService.class);
26+
advisedSupport.setTargetSource(targetSource);
27+
28+
// 2. 设置拦截器(Advice)
29+
TimerInterceptor timerInterceptor = new TimerInterceptor();
30+
advisedSupport.setMethodInterceptor(timerInterceptor);
31+
32+
// 3. 创建代理(Proxy)
33+
Cglib2AopProxy cglib2AopProxy = new Cglib2AopProxy(advisedSupport);
34+
HelloWorldService helloWorldServiceProxy = (HelloWorldService) cglib2AopProxy.getProxy();
35+
36+
// 4. 基于AOP的调用
37+
helloWorldServiceProxy.helloWorld();
38+
39+
}
40+
}

src/test/java/us/codecraft/tinyioc/aop/JdkDynamicAopProxyTest.java

+5-3
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import org.junit.Test;
44
import us.codecraft.tinyioc.HelloWorldService;
5+
import us.codecraft.tinyioc.HelloWorldServiceImpl;
56
import us.codecraft.tinyioc.context.ApplicationContext;
67
import us.codecraft.tinyioc.context.ClassPathXmlApplicationContext;
78

@@ -20,7 +21,8 @@ public void testInterceptor() throws Exception {
2021
// --------- helloWorldService with AOP
2122
// 1. 设置被代理对象(Joinpoint)
2223
AdvisedSupport advisedSupport = new AdvisedSupport();
23-
TargetSource targetSource = new TargetSource(helloWorldService, HelloWorldService.class);
24+
TargetSource targetSource = new TargetSource(helloWorldService, HelloWorldServiceImpl.class,
25+
HelloWorldService.class);
2426
advisedSupport.setTargetSource(targetSource);
2527

2628
// 2. 设置拦截器(Advice)
@@ -31,8 +33,8 @@ public void testInterceptor() throws Exception {
3133
JdkDynamicAopProxy jdkDynamicAopProxy = new JdkDynamicAopProxy(advisedSupport);
3234
HelloWorldService helloWorldServiceProxy = (HelloWorldService) jdkDynamicAopProxy.getProxy();
3335

34-
// 4. 基于AOP的调用
35-
helloWorldServiceProxy.helloWorld();
36+
// 4. 基于AOP的调用
37+
helloWorldServiceProxy.helloWorld();
3638

3739
}
3840
}

src/test/resources/tinyioc.xml

+2-2
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,10 @@
1616
<property name="outputService" ref="outputService"></property>
1717
</bean>
1818

19-
<bean id="timeInterceptor" class="us.codecraft.tinyioc.aop.TimerInterceptor"></bean>
20-
2119
<bean id="autoProxyCreator" class="us.codecraft.tinyioc.aop.AspectJAwareAdvisorAutoProxyCreator"></bean>
2220

21+
<bean id="timeInterceptor" class="us.codecraft.tinyioc.aop.TimerInterceptor"></bean>
22+
2323
<bean id="aspectjAspect" class="us.codecraft.tinyioc.aop.AspectJExpressionPointcutAdvisor">
2424
<property name="advice" ref="timeInterceptor"></property>
2525
<property name="expression" value="execution(* us.codecraft.tinyioc.*.*(..))"></property>

0 commit comments

Comments
 (0)