Skip to content

Commit acf5ce3

Browse files
author
monsoon
committed
add AOP support with cglib
1 parent 2fd2fbe commit acf5ce3

File tree

14 files changed

+337
-10
lines changed

14 files changed

+337
-10
lines changed
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package com.xfj.frameworktest.aspect;
2+
3+
import simple.xfj.framework.annotation.Aspect;
4+
import simple.xfj.framework.annotation.Controller;
5+
import simple.xfj.framework.proxy.AspectProxy;
6+
7+
import java.lang.reflect.Method;
8+
9+
/**
10+
* Created by asus on 2017/4/20.
11+
*/
12+
@Aspect(value = Controller.class)//声明这个类是增强类,并且去拦截被所有被controller标注的类的方法
13+
public class TimeAspect extends AspectProxy{
14+
@Override
15+
public void before(Class<?> cls, Method method, Object[] params) throws Throwable {
16+
super.before(cls, method, params);
17+
System.out.println("前置增强");
18+
System.out.println(System.currentTimeMillis());
19+
}
20+
21+
@Override
22+
public void after(Class<?> cls, Method method, Object[] params, Object result) throws Throwable {
23+
super.after(cls, method, params, result);
24+
System.out.println("后置增强");
25+
System.out.println(System.currentTimeMillis());
26+
}
27+
28+
public static void main(String[] agrs){
29+
System.out.println(AspectProxy.class.isAssignableFrom(TimeAspect.class));
30+
}
31+
}

frameworktest/src/main/java/com/xfj/frameworktest/controller/CartController.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,19 +18,19 @@ public class CartController {
1818
@Autowired
1919
private CartService cartService;
2020

21-
@Action(value = "/helloworld",method = RequestMethod.POST)
21+
@Action(value = "/helloworld",method = RequestMethod.GET)
2222
public Data getRequest(Param param){
2323
Student s = new Student("xfh",24);
2424
Data data = new Data();
2525
data.setModel(s);
2626
return data;
2727
}
2828

29-
public CartService getCartService() {
29+
public CartService getCartService() {
3030
return cartService;
3131
}
3232

33-
public void setCartService(CartService cartService) {
33+
public void setCartService(CartService cartService) {
3434
this.cartService = cartService;
35-
}
36-
}
35+
}
36+
}

pom.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,12 @@
7777
<artifactId>commons-dbcp</artifactId>
7878
<version>1.4</version>
7979
</dependency>
80+
<!-- cglib代理库-->
81+
<dependency>
82+
<groupId>cglib</groupId>
83+
<artifactId>cglib</artifactId>
84+
<version>2.2.2</version>
85+
</dependency>
8086

8187

8288

src/main/java/simple/xfj/framework/DispatcherServlet.java

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,15 +47,13 @@ public void init(ServletConfig config) throws ServletException {
4747
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
4848
String method = req.getMethod().toLowerCase();
4949
String requestPath = req.getPathInfo();
50-
System.out.println(requestPath);
5150
Request request = new Request(method,requestPath);
5251
Handler handler = ControllerHelper.getActionMap().get(request);
5352
if(null != handler){
5453
Class<?> handlerClass = handler.getControllerClass();
5554
Object handlerBean = BeanHelper.getClassBean(handlerClass);
5655
//创建param
5756
Param param = getParam(req);
58-
System.out.println(handler.getActionMethod().getName());
5957
Object res = ReflectionUtil.methodInvoke(handler.getActionMethod(), handlerBean, param);
6058
try {
6159
doResult(req,resp,res);
@@ -82,7 +80,6 @@ private Param getParam(HttpServletRequest req){
8280
String[] nameValue = StringParam.split("&");
8381
if(nameValue != null && nameValue.length > 0){
8482
for(int i = 0; i < nameValue.length;i++){
85-
System.out.println(nameValue[i]);
8683
String[] pair = nameValue[i].split("=");
8784
paramMap.put(pair[0],pair[1]);
8885
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package simple.xfj.framework.annotation;
2+
3+
import java.lang.annotation.*;
4+
5+
/**
6+
* Created by asus on 2017/4/20.
7+
*/
8+
@Target(ElementType.TYPE)
9+
@Retention(RetentionPolicy.RUNTIME)
10+
public @interface Aspect {
11+
Class<? extends Annotation> value();
12+
}

src/main/java/simple/xfj/framework/bootstarp/HelperInitiler.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package simple.xfj.framework.bootstarp;
22

33
import simple.xfj.framework.annotation.Controller;
4+
import simple.xfj.framework.helper.AopHelper;
45
import simple.xfj.framework.helper.BeanHelper;
56
import simple.xfj.framework.helper.ClassHelper;
67
import simple.xfj.framework.helper.IocHelper;
@@ -15,6 +16,7 @@ public static void init(){
1516
Class[] clazzs = new Class[]{
1617
ClassHelper.class,
1718
BeanHelper.class,
19+
AopHelper.class,// AopHelper要在beanHelper之后,IocHelper之前初始化
1820
IocHelper.class,
1921
Controller.class
2022
};
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
package simple.xfj.framework.helper;
2+
3+
import simple.xfj.framework.annotation.Aspect;
4+
import simple.xfj.framework.proxy.AspectProxy;
5+
import simple.xfj.framework.proxy.Proxy;
6+
import simple.xfj.framework.proxy.ProxyManager;
7+
import simple.xfj.framework.util.ReflectionUtil;
8+
9+
import java.lang.annotation.Annotation;
10+
import java.util.*;
11+
12+
/**
13+
* Created by asus on 2017/4/20.
14+
*/
15+
public class AopHelper {
16+
17+
static {
18+
//类加载时初始化AOP,并将其设置到Bean中
19+
Map<Class<?>, List<Proxy>> target2ProxyList = getTarget2ProxyList();
20+
if(null != target2ProxyList && target2ProxyList.size() > 0){
21+
Set<Map.Entry<Class<?>, List<Proxy>>> entries = target2ProxyList.entrySet();
22+
for(Map.Entry<Class<?>, List<Proxy>> entry: entries){
23+
Class clazz = entry.getKey();
24+
List<Proxy> proxyList = entry.getValue();
25+
Object bean = ProxyManager.getProxy(clazz, proxyList);
26+
BeanHelper.setBean(clazz,bean);
27+
}
28+
}
29+
}
30+
31+
/**
32+
* 获取切面要去增强的所有类
33+
* @param aspect
34+
* @return
35+
*/
36+
private static Set<Class<?>> getTargetClassSet(Aspect aspect){
37+
Set<Class<?>> targetClass = new HashSet<Class<?>>();
38+
if(aspect != null){
39+
Class<? extends Annotation> annotation = aspect.value();
40+
if(annotation != null && !annotation.equals(Aspect.class)){
41+
Set<Class<?>> classSetByAnnoation = ClassHelper.getClassSetByAnnoation(annotation);
42+
targetClass.addAll(classSetByAnnoation);
43+
}
44+
}
45+
return targetClass;
46+
}
47+
48+
/**
49+
* 获取所有的切面类aspest与目标类的映射关系
50+
*/
51+
52+
private static Map<Class<? extends Proxy>, Set<Class<?>>> getAspect2Target(){
53+
Map<Class<? extends Proxy>, Set<Class<?>>> proxyMap = new HashMap<Class<? extends Proxy>, Set<Class<?>>>();
54+
Set<Class<?>> aspectClassSet = ClassHelper.getClassSetBySuper(AspectProxy.class);
55+
for(Class clazz : aspectClassSet){
56+
if(clazz.isAnnotationPresent(Aspect.class)){
57+
Aspect aspect = (Aspect)clazz.getAnnotation(Aspect.class);
58+
Set<Class<?>> classSet = getTargetClassSet(aspect);
59+
proxyMap.put(clazz,classSet);
60+
}
61+
}
62+
return proxyMap;
63+
}
64+
65+
/**
66+
* 将每个目标类所需要增强的增强类整理成1对多的map集合以便在beanHelper中用去取代原来的原始bean
67+
* @return
68+
*/
69+
private static Map<Class<?>,List<Proxy>> getTarget2ProxyList(){
70+
Map<Class<?>,List<Proxy>> clazz4Proxy = new HashMap<Class<?>, List<Proxy>>();
71+
Map<Class<? extends Proxy>, Set<Class<?>>> aspect2Target = getAspect2Target();
72+
Set<Map.Entry<Class<? extends Proxy>, Set<Class<?>>>> entries = aspect2Target.entrySet();
73+
for(Map.Entry<Class<? extends Proxy>, Set<Class<?>>> entry : entries){
74+
Class<? extends Proxy> proxyClass = entry.getKey();
75+
Set<Class<?>> targetSet = entry.getValue();
76+
for(Class cls : targetSet){
77+
List<Proxy> proxies = clazz4Proxy.get(cls);
78+
if(null == proxies){
79+
proxies = new ArrayList<Proxy>();
80+
proxies.add(ReflectionUtil.newInstance(proxyClass));
81+
clazz4Proxy.put(cls,proxies);
82+
}else{
83+
proxies.add(ReflectionUtil.newInstance(proxyClass));
84+
}
85+
}
86+
}
87+
return clazz4Proxy;
88+
}
89+
90+
}

src/main/java/simple/xfj/framework/helper/BeanHelper.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,4 +36,9 @@ public static <T> T getClassBean(Class<T> clazz){
3636
}
3737
return null;
3838
}
39+
40+
public static void setBean(Class<?> clazz,Object object){
41+
//用于在aop生成代理类后,替换bean容器里的原有目标类,
42+
beanMap.put(clazz,object);
43+
}
3944
}

src/main/java/simple/xfj/framework/helper/ClassHelper.java

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import simple.xfj.framework.annotation.Service;
1111
import simple.xfj.framework.util.ClassUtil;
1212

13+
import java.lang.annotation.Annotation;
1314
import java.util.HashSet;
1415
import java.util.Set;
1516

@@ -76,4 +77,36 @@ public static Set<Class<?>> getBeanSet(){
7677
return beanSet;
7778
}
7879

80+
81+
/**
82+
* 获得某个父类下的所有子类
83+
* @param clazz
84+
* @return
85+
*/
86+
public static Set<Class<?>> getClassSetBySuper(Class<?> clazz){
87+
Set<Class<?>> classSet = new HashSet<Class<?>>();
88+
for(Class cls : CLAZZ_SET){
89+
if(clazz.isAssignableFrom(cls) && !cls.equals(clazz)){
90+
classSet.add(cls);
91+
}
92+
}
93+
return classSet;
94+
}
95+
96+
/**
97+
* 获取被某个注解注释的类
98+
* @param annoationClass
99+
* @return
100+
*/
101+
public static Set<Class<?>> getClassSetByAnnoation(Class<? extends Annotation> annoationClass){
102+
Set<Class<?>> classSet = new HashSet<Class<?>>();
103+
for(Class cls : CLAZZ_SET){
104+
if(cls.isAnnotationPresent(annoationClass)){
105+
classSet.add(cls);
106+
}
107+
}
108+
return classSet;
109+
}
110+
111+
79112
}
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
package simple.xfj.framework.proxy;
2+
3+
import org.slf4j.Logger;
4+
import org.slf4j.LoggerFactory;
5+
6+
import java.lang.reflect.Method;
7+
8+
/**
9+
* Created by asus on 2017/4/20.
10+
*/
11+
public class AspectProxy implements Proxy{
12+
13+
14+
private static final Logger LOGGER = LoggerFactory.getLogger(AspectProxy.class);
15+
16+
public Object doProxy(ProxyChain proxyChain) throws Throwable {
17+
Object res = null;
18+
Class<?> targetClass = proxyChain.getTargetClass();
19+
Object[] methodParams = proxyChain.getMethodParams();
20+
Method targetMethod = proxyChain.getTargetMethod();
21+
begin();
22+
try{
23+
if(intercept(targetClass,targetMethod,methodParams)){
24+
before(targetClass,targetMethod,methodParams);
25+
res = proxyChain.doProxyChain();
26+
after(targetClass,targetMethod,methodParams,res);
27+
}else{
28+
res = proxyChain.doProxyChain();
29+
}
30+
}catch (Exception e){
31+
LOGGER.error("invoke method chain proxy error" + targetMethod.getName());
32+
throw e;
33+
}finally {
34+
end();
35+
}
36+
return res;
37+
}
38+
public void begin(){
39+
40+
}
41+
42+
public boolean intercept(Class<?> cls,Method method,Object[] params) throws Throwable{
43+
return true;
44+
}
45+
public void before(Class<?> cls,Method method,Object[] params) throws Throwable{
46+
System.out.println("ni hao");
47+
48+
}
49+
50+
public void after(Class<?> cls,Method method,Object[] params,Object result) throws Throwable{
51+
System.out.println("ni huai");
52+
}
53+
public void end(){
54+
55+
}
56+
57+
58+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package simple.xfj.framework.proxy;
2+
3+
/**
4+
* Created by asus on 2017/4/20.
5+
*/
6+
public interface Proxy {
7+
8+
Object doProxy(ProxyChain proxyChain) throws Throwable;
9+
}
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
package simple.xfj.framework.proxy;
2+
3+
import net.sf.cglib.proxy.MethodProxy;
4+
5+
import java.lang.reflect.Method;
6+
import java.util.ArrayList;
7+
import java.util.List;
8+
9+
/**
10+
* Created by asus on 2017/4/20.
11+
*/
12+
public class ProxyChain {
13+
14+
private final Class<?> targetClass;
15+
private final Object target;
16+
private final Method targetMethod;
17+
private final MethodProxy methodProxy;
18+
private final Object[] methodParams;
19+
20+
private List<Proxy> proxyList = new ArrayList<Proxy>();
21+
22+
private int proxyIndex = 0;
23+
24+
public ProxyChain(Class<?> targetClass, Object target, Method targetMethod, MethodProxy methodProxy, Object[] methodParams) {
25+
this.targetClass = targetClass;
26+
this.target = target;
27+
this.targetMethod = targetMethod;
28+
this.methodProxy = methodProxy;
29+
this.methodParams = methodParams;
30+
}
31+
32+
public Class<?> getTargetClass() {
33+
return targetClass;
34+
}
35+
36+
public Method getTargetMethod() {
37+
return targetMethod;
38+
}
39+
40+
public Object[] getMethodParams() {
41+
return methodParams;
42+
}
43+
44+
public ProxyChain setProxyList(List proxyList){
45+
this.proxyList = proxyList;
46+
return this;
47+
}
48+
49+
public Object doProxyChain() throws Throwable{
50+
Object res = null;
51+
if(null != proxyList && proxyIndex < proxyList.size()){
52+
//将链条中的代理一个一个的添加到代理方法中
53+
res = proxyList.get(proxyIndex++).doProxy(this);
54+
}else{
55+
res = methodProxy.invokeSuper(target,methodParams);
56+
}
57+
return res;
58+
}
59+
60+
}

0 commit comments

Comments
 (0)