Spring提供俩种方式实现AOP.docx
- 文档编号:6361845
- 上传时间:2023-01-05
- 格式:DOCX
- 页数:43
- 大小:28.72KB
Spring提供俩种方式实现AOP.docx
《Spring提供俩种方式实现AOP.docx》由会员分享,可在线阅读,更多相关《Spring提供俩种方式实现AOP.docx(43页珍藏版)》请在冰豆网上搜索。
Spring提供俩种方式实现AOP
AOP是AspectOrientedProgramming的缩写,意思是面向方面编程,一种新兴的编程技术。
AOP实际是GoF设计模式的延续,设计模式孜孜不倦追求的是调用者和被调用者之间的解耦,
AOP可以说也是这种目标的一种实现。
它可以解决OOP和过程化方法不能够很好解决的横切
(crosscut)问题,
如:
事务、安全、日志等横切关注。
当未来系统变得越来越复杂,
横切关注点就成为一个大问题的时候,AOP就可以很轻松的解决横切关注点这个问题。
比如有这样一个情景:
Java代码
1.public class AccountManager {
2. private static final sysLogger = SystemLogger.getInstance();
3. private AuthorizationManager authMgr = new AuthorizationManager();
4.
5. public void transferFunds(String from, String to, int amount) {
6. sysLogger.log("transfer funds from " + from + " to " + to);
7. if(authMgr.accessAble(from) && authMgr.accessAble(to)) {
8. sysLogger.log("access successfully");
9. CustomerAccount from = findAccount(from);
10. CustomerAccount to = findAccount(to);
11. from.debit(amount);
12. to.credit(amount);
13. } else {
14. sysLogger.log("access deny");
15. }
16. sysLogger.log("transfer funds from " + from + " to " + to + " $" + amount + " successfully!
");
17. }
18.}
publicclassAccountManager{
privatestaticfinalsysLogger=SystemLogger.getInstance();
privateAuthorizationManagerauthMgr=newAuthorizationManager();
publicvoidtransferFunds(Stringfrom,Stringto,intamount){
sysLogger.log("transferfundsfrom"+from+"to"+to);
if(authMgr.accessAble(from)&&authMgr.accessAble(to)){
sysLogger.log("accesssuccessfully");
CustomerAccountfrom=findAccount(from);
CustomerAccountto=findAccount(to);
from.debit(amount);
to.credit(amount);
}else{
sysLogger.log("accessdeny");
}
sysLogger.log("transferfundsfrom"+from+"to"+to+"$"+amount+"successfully!
");
}
}
这个例子虽然是很好的面向对象代码,但是在业务处理逻辑中夹杂这日志处理和权限判断,变得复杂混乱.
在AOP中,正交关注点(如安全和日志记录)被识别为系统中的常见横切关注点。
说它们是横切,
是因为它们总是切入模块(如包、类和代码文件)的多个单位。
也许横切关注点可能不是核心业务逻辑的一部分,但是它们是应用程序的基本部分。
AOP的实现主要是通过方法的拦截实现.在不使用AOP框架的情况下,我们可以通过JDK提供的动态代理来实现方法的拦截
注意:
使用JDK提供的动态代理实现
要求我们的目标对象必须实现接口
IUserBean接口
Java代码
1.package com.royzhou.aop;
2.
3.public interface IUserBean {
4.
5. public void getUser();
6.
7. public void addUser();
8.
9. public void updateUser();
10.
11. public void deleteUser();
12.}
packagecom.royzhou.aop;
publicinterfaceIUserBean{
publicvoidgetUser();
publicvoidaddUser();
publicvoidupdateUser();
publicvoiddeleteUser();
}
IUserBean实现类UserBean.java
Java代码
1.package com.royzhou.aop;
2.
3.public class UserBean implements IUserBean {
4.
5. private String user = null;
6.
7. public UserBean() {
8. }
9.
10. public UserBean(String user) {
11. this.user = user;
12. }
13.
14. public void setUser(String user) {
15. this.user = user;
16. }
17.
18. public void addUser() {
19. System.out.println("this is addUser() method!
");
20. }
21.
22. public void deleteUser() {
23. System.out.println("this is deleteUser() method!
");
24. }
25.
26. public void getUser() {
27. System.out.println("this is getUser() method!
");
28. }
29.
30. public void updateUser() {
31. System.out.println("this is updateUser() method!
");
32. }
33.}
packagecom.royzhou.aop;
publicclassUserBeanimplementsIUserBean{
privateStringuser=null;
publicUserBean(){
}
publicUserBean(Stringuser){
this.user=user;
}
publicvoidsetUser(Stringuser){
this.user=user;
}
publicvoidaddUser(){
System.out.println("thisisaddUser()method!
");
}
publicvoiddeleteUser(){
System.out.println("thisisdeleteUser()method!
");
}
publicvoidgetUser(){
System.out.println("thisisgetUser()method!
");
}
publicvoidupdateUser(){
System.out.println("thisisupdateUser()method!
");
}
}
我们希望在UserBean执行方法之前先检查userName是不是为空,以此做为权限判断.
当然我们可以在没个方法里面去加这些判断,但是这需要为每个方法都添加同样的判断,维护不便.
使用JDK提供的动态代理技术可以很方便的实现上面的需求:
通过java.lang.reflect.Proxy;提供的
publicstaticObjectnewProxyInstance(ClassLoaderloader,
Class
>[]interfaces,
InvocationHandlerh)
方法可以生成一个动态代理对象
其中
loader是类装载器
interfaces是目标对象实现的一系列接口
h是一个实现InvocationHandler接口的类,我们对代理对象的所有操作都经过它处理
这样我们就可以拦截到UserBean的方法,在方法执行前先判断是否有权限,如果有则执行方法,
没有权限的话就不执行方法.
编写我们的代理类:
JDKProxy.java
Java代码
1.package com.royzhou.aop;
2.
3.import java.lang.reflect.InvocationHandler;
4.import java.lang.reflect.Method;
5.import java.lang.reflect.Proxy;
6.
7.public class JDKProxy implements InvocationHandler {
8.
9. private Object targetObject;
10.
11. public Object createProxyObject(Object targetObject) {
12. this.targetObject = targetObject;
13. //生成代理对象
14. return Proxy.newProxyInstance(this.targetObject.getClass().getClassLoader(),this.targetObject.getClass().getInterfaces(),this);
15. }
16.
17. public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
18. UserBean userBean = (UserBean) targetObject;
19. String userName = userBean.getUserName();
20. Object result = null;
21. //权限判断
22. if(userName!
=null && !
"".equals(userName)) {
23. //调用目标对象的方法
24. result = method.invoke(targetObject, args);
25. }
26. return result;
27. }
28.}
packagecom.royzhou.aop;
importjava.lang.reflect.InvocationHandler;
importjava.lang.reflect.Method;
importjava.lang.reflect.Proxy;
publicclassJDKProxyimplementsInvocationHandler{
privateObjecttargetObject;
publicObjectcreateProxyObject(ObjecttargetObject){
this.targetObject=targetObject;
//生成代理对象
returnProxy.newProxyInstance(this.targetObject.getClass().getClassLoader(),this.targetObject.getClass().getInterfaces(),this);
}
publicObjectinvoke(Objectproxy,Methodmethod,Object[]args)throwsThrowable{
UserBeanuserBean=(UserBean)targetObject;
StringuserName=userBean.getUserName();
Objectresult=null;
//权限判断
if(userName!
=null&&!
"".equals(userName)){
//调用目标对象的方法
result=method.invoke(targetObject,args);
}
returnresult;
}
}
通过调用createProxyObject可以生成代理对象,
编写测试类如下:
Java代码
1.package com.royzhou.aop;
2.
3.public class TestProxy {
4.
5. public static void main(String[] args) {
6. JDKProxy jProxy = new JDKProxy();
7. IUserBean userBean = (IUserBean) jProxy.createProxyObject(new UserBean("royzhou"));
8. userBean.addUser();
9. }
10.}
packagecom.royzhou.aop;
publicclassTestProxy{
publicstaticvoidmain(String[]args){
JDKProxyjProxy=newJDKProxy();
IUserBeanuserBean=(IUserBean)jProxy.createProxyObject(newUserBean("royzhou"));
userBean.addUser();
}
}
执行成功后输出:
thisisaddUser()method!
再次修改测试类:
Java代码
1.package com.royzhou.aop;
2.
3.public class TestProxy {
4.
5. public static void main(String[] args) {
6. JDKProxy jProxy = new JDKProxy();
7. IUserBean userBean = (IUserBean) jProxy.createProxyObject(new UserBean());
8. userBean.addUser();
9. }
10.}
packagecom.royzhou.aop;
publicclassTestProxy{
publicstaticvoidmain(String[]args){
JDKProxyjProxy=newJDKProxy();
IUserBeanuserBean=(IUserBean)jProxy.createProxyObject(newUserBean());
userBean.addUser();
}
}
即当用户没有权限时,控制台不输出东西,说明我们拦截方法对其做的权限判断生效了.
从上面这个例子可以成功拦截了调用的方法并对其做了相应的处理
如果不使用JDK提供的Proxy类
通过cglib创建代理类,好处是不要求我们的目标对象实现接口
Enhancerenhancer=newEnhancer();
enhancer.setSuperclass(this.targetObject.getClass());
enhancer.setCallback(this);//回调,参数是一个实现MethodInterceptor接口的类,我们对代理对象的所有操作都经过它处理
returnenhancer.create();//创建代理对象
修改UserBean去掉IUserBean接口
Java代码
1.package com.royzhou.aop;
2.
3.public class UserBean {
4.
5. private String userName = null;
6.
7. public UserBean() {
8. }
9.
10. public UserBean(String userName) {
11. this.userName = userName;
12. }
13.
14. public void addUser() {
15. System.out.println("this is addUser() method!
");
16. }
17.
18. public void deleteUser() {
19. System.out.println("this is deleteUser() method!
");
20. }
21.
22. public void getUser() {
23. System.out.println("this is getUser() method!
");
24. }
25.
26. public void updateUser() {
27. System.out.println("this is updateUser() method!
");
28. }
29.
30. public String getUserName() {
31. return userName;
32. }
33.
34. public void setUserName(String userName) {
35. this.userName = userName;
36. }
37.}
packagecom.royzhou.aop;
publicclassUserBean{
privateStringuserName=null;
publicUserBean(){
}
publicUserBean(StringuserName){
this.userName=userName;
}
publicvoidaddUser(){
System.out.println("thisisaddUser()method!
");
}
publicvoiddeleteUser(){
System.out.println("thisisdeleteUser()method!
");
}
publicvoidgetUser(){
System.out.println("thisisgetUser()method!
");
}
publicvoidupdateUser(){
System.out.println("thisisupdateUser()method!
");
}
publicStringgetUserName(){
returnuserName;
}
publicvoidsetUserName(StringuserName){
this.userName=userName;
}
}
通过cglib创建代理类
CGLibProxy.java
Java代码
1.package com.royzhou.aop;
2.
3.import java.lang.reflect.Method;
4.
5.import net.
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- Spring 提供 方式 实现 AOP