一、代理模式实现aop
1
2
3
4
5
6
7
8
9
10
|
public interface IHello {
void sayHello(String name);
} public class Hello implements IHello {
@Override
public void sayHello(String name) {
System.out.println(name+ " say hello" );
}
} |
代理类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
public class HelloProxy implements IHello {
private IHello hello;
public HelloProxy(IHello hello){
this .hello=hello;
}
@Override
public void sayHello(String name) {
System.out.println( "before...." );
hello.sayHello(name);
System.out.println( "after...." );
}
} |
客户端
1
2
3
4
5
6
7
|
public class Test {
public static void main(String[] args){
IHello hello= new HelloProxy( new Hello());
hello.sayHello( "persia" );
}
} |
二、JDK的动态代理反射实现aop
JDK动态代理只能代理接口
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
/** * 使用JDK提供的动态代理
* @author scipio
* @created 2013-10-21
*/
public class DynaProxyHello implements InvocationHandler{
private Object target;
//动态生成代理对象
public Object bind(Object target){
this .target=target;
return Proxy.newProxyInstance( this .target.getClass().getClassLoader(), this .target.getClass().getInterfaces(), this );
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println( "before..... " );
Object result=method.invoke(target,args);
System.out.println( "after....." );
return result;
}
} |
客户端
1
2
3
4
5
6
7
8
9
10
11
12
|
public class Test {
public static void main(String[] args){
/**
* 只能代理接口
*/
IHello hello= (IHello) new DynaProxyHello().bind( new Hello());
// Hello hello = (Hello) new DynaProxyHello().bind(new Hello()); hello.sayHello( "persia" );
}
} |
三、Aspect方式(JDK实现)
1、定义拦截后要执行的方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
/** * 拦截指定方法后要执行的方法
* @author scipio
* @created 2013-10-21
*/
public class CrossCutting {
public void before(){
System.out.println( "before..." );
}
public void after(){
System.out.println( "after..." );
}
} |
2、模拟Aop
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
|
/** * 使用java的反射
* 进行aop功能的模拟
* @author scipio
* @created 2013-10-21
*/
public class Aop {
private static CrossCutting cut= new CrossCutting();
private static ReflectUtils rfBefore= new ReflectUtils(cut, "before" );
private static ReflectUtils rfAfter= new ReflectUtils(cut, "after" );
public static void beforeAdvice(Object target,String methodName,Object ... params){
Class cls=target.getClass();
Method[] methods=cls.getDeclaredMethods();
for ( int i= 0 ;i<methods.length;i++){
if (methods[i].getName().equals(methodName)){
rfBefore.invokeMethod();
new ReflectUtils(target,methodName,params).invokeMethod();
}
}
}
public static void afterAdvice(Object target,String methodName,Object... params){
Class cls=target.getClass();
Method[] methods=cls.getDeclaredMethods();
for ( int i= 0 ;i<methods.length;i++){
if (methods[i].getName().equals(methodName)){
new ReflectUtils(target,methodName,params).invokeMethod();
rfAfter.invokeMethod();
}
}
}
public static void aroundAdvice(Object target,String methodName,Object... params){
Class cls=target.getClass();
Method[] methods=cls.getDeclaredMethods();
for ( int i= 0 ;i<methods.length;i++){
if (methods[i].getName().equals(methodName)){
rfBefore.invokeMethod();
new ReflectUtils(target,methodName,params).invokeMethod();
rfAfter.invokeMethod();
}
}
}
} |
3、拦截对象
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
/** * 要被拦截的方法
* @author scipio
* @created 2013-10-21
*/
public interface Crud {
public void add(String user);
public void modify(String user);
public void delete(String user);
} /** * 要被拦截的方法
* @author scipio
* @created 2013-10-21
*/
public class CrudImpl implements Crud {
@Override
public void add(String user) {
System.out.println( "new user:" );
}
@Override
public void modify(String user) {
System.out.println( "modify user" );
}
@Override
public void delete(String user) {
System.out.println( "delete user" );
}
} |
4、客户端及工具类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
|
public class Test {
public static void main(String[] args){
Crud crud= new CrudImpl();
Aop.beforeAdvice(crud, "modify" , "persia" );
}
} /** * java反射的一些帮助方法
* 通过传入的类,拦截要执行的方法名
* 返回后直接invoke即可
* 具体见aop
* 无其他意义,不是经典模式,可以去掉
* @author scipio
* @created 2013-10-21
*/
public class ReflectUtils {
private Class targetClass;
private Object target;
private Method targetMethod;
private Object[] params;
public ReflectUtils(Object target,String methodName,Object ... params){
this .target=target;
this .targetClass=target.getClass();
this .params=params;
Class[] cls= new Class[params.length];
for ( int i= 0 ;i<params.length;i++){
cls[i]=params[i].getClass();
}
try {
this .targetMethod=targetClass.getMethod(methodName,cls);
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
}
public void invokeMethod(){
try {
this .targetMethod.invoke(target,params);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
} |
四、Aspect方式(Cglib实现)
1、拦截后要执行的方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
/** * 通过cglib进行拦截
* @author scipio
* @created 2013-10-21
*/
public class AroundCutting implements MethodInterceptor{
@Override
public Object intercept(Object o, Method method, Object[] args, MethodProxy proxy) throws Throwable {
System.out.println( "before...." +method);
//直接invoke会造成stack over flow
// Object result = proxy.invoke(o, args); Object result = proxy.invokeSuper(o, args);
System.out.println( "after..." +method);
return result;
}
} |
2、Cglib模拟aop
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
|
/** * cglib实现aop
* @author scipio
* @created 2013-10-21
*/
public class CglibAOP {
private Enhancer enhancer = new Enhancer();
/**
* 使用Cglib进行动态代理,是创建一个子类继承至目标类,所以不需要像GDK动态代理那样提供一个接口,这样节约了类的个数。
* JDK动态代理的特点:不能代理类,只能代理接口
* CGLIB动态代理的特点:能代理类和接口,不能代理final类
* 动态代理的本质:用来实现对目标对象进行增强,最终表现为类,只不过是动态创建子类,不用手工生成子类。
* @param clz
* @return
*/
private MethodInterceptor interceptor;
public CglibAOP(MethodInterceptor interceptor){
this .interceptor=interceptor;
}
public Object getProxy(Class clz){
//生成指定类对象的子类,也就是重写类中的业务函数
enhancer.setSuperclass(clz);
//这里是回调函数,加入intercept()函数
enhancer.setCallback(interceptor);
//创建这个子类对象
return enhancer.create();
}
} |
3、被拦截对象
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
/** * 要被拦截的方法
* @author caibosi
* @created 2013-10-21
*/
public class CrudImpl {
public void add(String user) {
System.out.println( "new user:" );
}
//用static方法的话,则拦截不了
public void modify(String user) {
System.out.println( "modify user" +user);
}
public void delete(String user) {
System.out.println( "delete user" );
}
} |
4、客户端
1
2
3
4
5
6
7
8
|
public class Test {
public static void main(String[] args){
CglibAOP aop= new CglibAOP( new AroundCutting());
CrudImpl crud= (CrudImpl) aop.getProxy(CrudImpl. class );
crud.modify( "modify name" );
}
} |
5、高级回调功能
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
|
/** * cglib callback filter
* 根据不同方法进行不同的拦截
* @author scipio
* @created 2013-10-24
*/
public class CglibCallbacks {
public static void main(String[] args){
//声明cglib增强类
Enhancer enhancer = new Enhancer();
//设置被代理类
enhancer.setSuperclass(CrudImpl. class );
//set callbacks
Callback[] callbacks = new Callback[]{
NoOp.INSTANCE, new AddCallback(), new ModifyCallback(), new DeleteCallback()
};
//设定拦截方法
enhancer.setCallbacks(callbacks);
//设定方法对应的拦截
enhancer.setCallbackFilter( new DaoFilter());
//通过增强类获取代理类
CrudImpl proxyCrud = (CrudImpl)enhancer.create();
proxyCrud.modify( "persia" );
proxyCrud.add( "linda" );
proxyCrud.delete( "susan" );
}
} class AddCallback implements MethodInterceptor{
@Override
public Object intercept(Object o, Method method, Object[] args, MethodProxy proxy) throws Throwable {
System.out.println( "before....cutting add method" );
Object result = proxy.invokeSuper(o, args);
System.out.println( "after...cutting add method" );
return result;
}
} class ModifyCallback implements MethodInterceptor{
@Override
public Object intercept(Object o, Method method, Object[] args, MethodProxy proxy) throws Throwable {
System.out.println( "before....cutting modify method" );
Object result = proxy.invokeSuper(o, args);
System.out.println( "after...cutting modify method" );
return result;
}
} class DeleteCallback implements MethodInterceptor{
@Override
public Object intercept(Object o, Method method, Object[] args, MethodProxy proxy) throws Throwable {
System.out.println( "before....cutting delete method" );
Object result = proxy.invokeSuper(o, args);
System.out.println( "after...cutting delete method" );
return result;
}
} /** * 此方法用来决定哪个方法
* 被那个callback拦截
* 返回index,对应callbacks数组
*/
class DaoFilter implements CallbackFilter{
@Override
public int accept(Method method) {
String methodName = method.getName();
System.out.println( "method:" +methodName);
if (methodName.equals( "delete" )){
return 3 ;
} else if (methodName.equals( "add" )){
return 1 ;
} else if (methodName.equals( "modify" )){
return 2 ;
}
//0对应了NoOp.INSTANCE的callback,表示不做任何事情
return 0 ;
}
} |
五、要点
1、JDK只能基于接口动态代理
2、Cglib基于接口和非final类代理,不能代理static方法
相关推荐
本篇文章将深入探讨如何通过Spring的注解方式实现AOP的细节。 首先,我们需要了解AOP的基本概念。AOP的核心是切面(Aspect),它封装了跨越多个对象的行为或责任。切点(Pointcut)定义了哪些方法会被通知(Advice...
本篇文章将详细探讨Spring实现AOP的四种主要方法:基于代理的方式、基于AspectJ的注解方式、基于XML的AOP配置以及基于Java的AOP配置。 1. 基于代理的实现 Spring的AOP支持两种代理类型:JDK动态代理和CGLIB代理。...
在C#中,实现AOP的方法多种多样,以下将详细介绍几种常见的实现方式。 1. **静态织入**: 静态织入是在编译时完成的,它通过编译器或者编译插件(如PostSharp)在目标类的代码中插入拦截逻辑。这种方式的优点是...
下面我们将详细探讨Spring实现AOP的四种主要方式。 1. **基于注解的AOP** Spring框架自2.5版本开始支持基于注解的AOP,这种方式无需XML配置,更加简洁直观。开发者可以在方法上使用`@Aspect`、`@Before`、`@After`...
总结一下,注解方式实现AOP编程主要包括以下几个步骤: 1. 创建一个`@Aspect`注解的类来定义切面。 2. 使用`@Pointcut`定义切点表达式。 3. 使用`@Before`, `@After`, `@AfterReturning`, `@AfterThrowing`, 或 `@...
通过以上步骤,我们可以使用Spring注解方式实现AOP,将关注点如日志、缓存等与业务逻辑分离,提高代码的可读性和可维护性。在实际项目中,可以灵活运用这些知识来优化代码结构,降低复杂性。希望本教程对理解和应用...
本篇文章将重点讲解如何通过XML配置方式在Spring中实现AOP。 首先,了解AOP的基本概念是必要的。AOP的核心是切面(Aspect),它封装了多个相关操作,形成了一个关注点。切点(Pointcut)定义了这些操作应用到何处,...
在net core2.2时,我当时就尝试过用autofac实现aop,但这次我不想用autofac,我用了一个更轻量级的框架,AspectCore。 用起来非常非常的简单,但一开始还是走了一点弯路,主要是网上都是net core3以下的教程,3以下...
**Java 动态代理**是Java标准库提供的另一种实现AOP的方式,主要针对接口。它允许我们创建一个代理类,该类在调用目标接口方法之前和之后执行自定义逻辑。这在处理基于接口的切面时非常有用。 ```java interface ...
本文将详细介绍Spring实现AOP的四种方式,包括基于代理的经典方式、@AspectJ注解驱动、纯POJO切面以及注入式AspectJ切面。 首先,理解AOP的基本概念: 1. **通知(Advice)**:通知定义了切面在何时执行,Spring支持...
总的来说,JavaEE CGLIB字节码增强方式提供了一种灵活的手段来实现AOP编程,它通过动态生成字节码创建目标类的子类,实现了对目标方法的拦截和增强,从而在不修改原有代码的基础上,增强了代码的功能和可维护性。...
本篇将通过注解方式探讨如何在Spring中实现AOP,基于提供的资源,我们可以看到一个实际的Demo项目结构。 首先,我们来看项目的基本结构: 1. `bin`目录:编译后的Java类文件会放在这里。 2. `.settings`目录:包含...
标题 "SpringXML方式实现AOP demo" 涉及到的是使用Spring框架通过XML配置来实现面向切面编程(AOP)的知识。面向切面编程是Spring框架的一个核心特性,它允许开发者在不修改原有业务代码的情况下,对系统进行横切...
Spring 实现 AOP 的四种方式 Spring 框架提供了四种方式来实现Aspect-Oriented Programming(AOP),分别是经典的基于代理的 AOP、@AspectJ 注解驱动的切面、纯 POJO 切面和注入式 AspectJ 切面。下面将详细介绍这...
在Spring中,注解方式实现AOP主要包括以下几个关键注解: 1. `@Aspect`:这个注解用于定义一个切面类,该类包含了若干个通知(advice)。 2. `@Before`:在目标方法执行前执行的通知,相当于传统的“前置通知”。 3...
**XML方式实现AOP编程** 在软件开发中,面向切面编程(Aspect-Oriented Programming,简称AOP)是一种编程范式,它旨在提高代码的可重用性和可维护性,通过将关注点分离,使得业务逻辑与横切关注点(如日志、事务...
这个"android 实现AOP 使用Aspect Kotlin版Demo"就是一个实例,展示了如何在Kotlin中利用AspectJ进行AOP编程。 首先,我们要了解AOP的基本概念。面向切面编程的核心在于“切面”和“通知”。切面是关注点的模块化,...
本文将详细解析Spring AOP的三种实现方式,帮助你深入理解这一重要概念。 首先,理解AOP的基本概念至关重要。AOP是一种编程范式,它允许开发者定义“切面”,即关注点的模块化,如日志、事务管理等。这些切面可以...
Spring 提供了两种方式来实现AOP代理:JDK动态代理和CGLIB代理。 1. **JDK动态代理**: - JDK动态代理基于Java的接口实现,适用于目标对象实现了接口的情况。Spring会为这个接口创建一个代理类,代理类在调用真实...
里面包括4个例子:(1)Spring实现AOP方式之一:基于XML配置的Spring AOP (2)Spring实现AOP方式之二:使用注解配置 Spring AOP (3)Spring AOP : AspectJ Pointcut 切点 (4)Spring AOP : Advice 声明 (通知注解)