一、代理模式实现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方法
相关推荐
在net core2.2时,我当时就尝试过用autofac实现aop,但这次我不想用autofac,我用了一个更轻量级的框架,AspectCore。 用起来非常非常的简单,但一开始还是走了一点弯路,主要是网上都是net core3以下的教程,3以下...
配置可以通过xml文件来进行,大概有四种方式: 1. 配置ProxyFactoryBean,显式地设置advisors, advice, target等(基于代理的AOP ) 2. 配置AutoProxyCreator,这种方式下,还是如以前一样使用定义的bean,但是从...
里面包括4个例子:(1)Spring实现AOP方式之一:基于XML配置的Spring AOP (2)Spring实现AOP方式之二:使用注解配置 Spring AOP (3)Spring AOP : AspectJ Pointcut 切点 (4)Spring AOP : Advice 声明 (通知注解)
在Spring1.2或之前的版本中,实现AOP的传统方式就是通过实现Spring的AOP API来定义Advice,并设置代理对象。Spring根据Adivce加入到业务流程的时机的不同,提供了四种不同的Advice:Before Advice、After Advice、...
2、基于AOP方式实现。 3、只需要在方法上声明@DistributedLock(可以是controller的方法也可以是service的公共方法)即可实现锁功能。 4、支持在@DistributedLock上动态传参,减少锁的颗粒度。
主要对Spring AOP的相关概念和简单的静态代理、动态代理以及常见的几种AOP配置方式做总结学习。主要包括:1. AOP的常见概念 2. 静态代理 3. jdk动态代理 4. Aspectj and Aspectjweaver 5. **aop-config** 6. CGLIB ...
在Spring1.2或之前的版本中,实现AOP的传统方式就是通过实现Spring的AOP API来定义Advice,并设置代理对象。Spring根据Adivce加入到业务流程的时机的不同,提供了四种不同的Advice:Before Advice、After Advice、...
此资源为文章中《代理设计模式:静态代理和动态代理的理解、实现与区别(优缺点)》与《 AOP动态代理声明式的3种配置方式过程与区别》的案例代码,可下载参考学习。
3.处理日志时,需要在每一个try-catch块包含一些处理代码,有时候异常处理的代码比正常执行代码还多,污染正常执行代码。 4.同样类型异常有不同的处理方式,使最终的处理变得复杂。 5.接口抛出异常,破坏封装,打破...
Spring AOP:以loC为基础讲解Spring下的AOP开发,讲解了3种AOP的开发方式,即使用@Aspect注释符、基于Schema的配置的开发方式和Spring API的开发方式,最后在实际的Java EE项目中实现5种Spring AOP功能(日志记录器...
3、了解Spring中两种动态代理方式的区别; 4、掌握基于XML和注解的AspectJ开发。 二、 实验内容 1、按图所示的类图结构,设计接口及其实现类,并完成另外两附加要求:(1)日志功能:在程序执行期间追踪正在发生的...
1. 首先完成一个接口的创建(里面有真正的想要实现的方法): public interface UserDAO{ public void add (); //想要实现的方法 } 2. 写一个真实的主题类实现...3. 写一个动态的代理类实现InvocationHandler接口:
一:实验目的 1、 理解Spring AOP原理和基本概念; 2、掌握基于XML/注解方式的AOP编程; 二:实验内容 1、 定义交易接口: public interface ...2、 基于XML实现AOP,使得账户余额变动前后进行信息提示; 3、基
此项目是实现以aop的形式,以annotion方式在实现方法上添加redis缓存 注意: 1.如果用maven打成jar包引入,只需修改一下配置问题 2.也可将代码copy到您的项目中。但要修改一些代码和配置文件 3.对象要实现...
(3)、非注解方式,业务代码侵入基本为零 (4)、懒事务处理方式,service层使用@Transactional注解的方法或者类只能走默认库(写库) (5)、AOP根据Dao层的方法名来判断读写库的切换,超出判断规则的只能走默认...
SpringAOP发展到现在出现的全部3种配置方式。由于Spring强大的向后兼容性,实际代码中往往会出现很多配置混杂的情况,而且居然还能工作,本文希望帮助大家理清楚这些知识。我们先来把它们的概念和关系说说清楚。AOP...
主体框架基于spring,而spring除了Ioc(依赖注入)、Aop(切面)外,其它与http相关的东西都是基于Servlet和Filter的,而Servlet、Filter是servlet容器Jetty按照j2ee标准做了具体实现。目前使用Spring的,更多是在...
1、集成com.baomidou的方式,引入dynamic-datasource...2、原生的方式,基于AOP手动实现多数据源; 3、项目代码完整,包含注释,能启动测试; 博客地址:https://blog.csdn.net/u011974797/article/details/130109195