SSH深度历险(十一) AOP原理及相关概念学习+xml配置实例(对比注解方式的优缺点)
接上一篇
SSH深度历险(十) AOP原理及相关概念学习+AspectJ注解方式配置spring AOP,本篇我们主要是来学习使用配置XML实现AOP
本文采用强制的CGLB代理方式
SecurityHandler这个通知类可以换成安全性检测、日志管理等等。
<span style="font-size:18px;"><span style="font-size:18px;"><span style="font-size:18px;">package com.bjpowernode.spring;
import org.aspectj.lang.JoinPoint;
public class SecurityHandler {
private void checkSecurity(JoinPoint joinPoint) {
for (int i=0; i<joinPoint.getArgs().length; i++) {
System.out.println(joinPoint.getArgs()[i]);
}
System.out.println(joinPoint.getSignature().getName());
System.out.println("-------checkSecurity-------");
}
}
</span></span></span>
UserManager接口
<span style="font-size:18px;"><span style="font-size:18px;"><span style="font-size:18px;">package com.bjpowernode.spring;
public interface UserManager {
public void addUser(String username, String password);
public void delUser(int userId);
public String findUserById(int userId);
public void modifyUser(int userId, String username, String password);
}
</span></span></span>
UserManagerImpl接口的实现
<span style="font-size:18px;"><span style="font-size:18px;"><span style="font-size:18px;">package com.bjpowernode.spring;
public class UserManagerImpl implements UserManager {
public void addUser(String username, String password) {
//checkSecurity();
System.out.println("---------UserManagerImpl.add()--------");
}
public void delUser(int userId) {
//checkSecurity();
System.out.println("---------UserManagerImpl.delUser()--------");
}
public String findUserById(int userId) {
//checkSecurity();
System.out.println("---------UserManagerImpl.findUserById()--------");
return "张三";
}
public void modifyUser(int userId, String username, String password) {
//checkSecurity();
System.out.println("---------UserManagerImpl.modifyUser()--------");
}
// private void checkSecurity() {
// System.out.println("-------checkSecurity-------");
// }
}
</span></span></span>
applicationContext.xml中进行配置( <!-- 强制使用CGLIB代理 --> )
<span style="font-size:18px;"><span style="font-size:18px;"><span style="font-size:18px;"><?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd">
<!-- 强制使用CGLIB代理 -->
<!--
<aop:aspectj-autoproxy proxy-target-class="true"/>
--> <bean id="userManager" class="com.bjpowernode.spring.UserManagerImpl"/>
<bean id="securityHandler" class="com.bjpowernode.spring.SecurityHandler"/> <aop:config>
<aop:aspect id="securityAspect" ref="securityHandler">
<!--
以add开头的方法
<aop:pointcut id="addAddMethod" expression="execution(* add*(..))"/>
-->
<!--
com.bjpowernode.spring包下所有的类所有的方法
<aop:pointcut id="addAddMethod" expression="execution(* com.bjpowernode.spring.*.*(..))"/>
-->
<aop:pointcut id="addAddMethod" expression="execution(* com.bjpowernode.spring.*.add*(..)) || execution(* com.bjpowernode.spring.*.del*(..))"/>
<aop:before method="checkSecurity" pointcut-ref="addAddMethod"/>
</aop:aspect>
</aop:config>
</beans>
</span></span></span>
Client客户端的调用
<span style="font-size:18px;"><span style="font-size:18px;"><span style="font-size:18px;">package com.bjpowernode.spring; import org.springframework.beans.factory.BeanFactory;
import org.springframework.context.support.ClassPathXmlApplicationContext; public class Client { public static void main(String[] args) {
BeanFactory factory = new ClassPathXmlApplicationContext("applicationContext.xml"); UserManagerImpl userManager = (UserManagerImpl)factory.getBean("userManager");
userManager.addUser("张三", "123"); } }
</span></span></span>
最终效果
AOP两种代理的区别
Jdk基于接口实现:JDK动态代理对实现了接口的类进行代理。
- CGLIB基于继承:CGLIB代理可以对类代理,主要对指定的类生成一个子类,因为是继承,所以目标类最好不要使用final声明。
- 如果目标对象实现了接口,默认情况下采用JDK的动态代理实现AOP,也可以强制使用CGLB生成代理实现;
- 如果目标对象没有实现接口,那么必须引入CGLB,spring会在JDK的动态代理和CGLB代理之间切换
通常情况下,鼓励使用jdk代理,因为业务一般都会抽象出一个接口,而且不用引入新的东西。如果是遗留的系统,以前没有实现接口,那么只能使用CGLIB。
一般情况下优先采用JDK动态代理,虽然其效率似乎比不上CGLIB代理,但是其对象用完之后可以正常释放。但是CGLIB代理每代理一个对象,都会产生一个新类。而类一旦载入JVM,按照大部分JVM的机制,这些新类占用的内存不会释放。J2EE程序一般运行时间都很长,内存上会有一些压力。
XML和AspectJ注解方式配置优缺点对比
用XML风格,则所有的切面、切点、通知等配置都写在一个或几个Spring配置文件里。这样的好处是,从配置文件中,就可以很清晰的看出系统中的有哪些切面,某个切面里使用那个的通知(advice)以及通知(advice)作用的切点。而在AspectJ风格中,在java程序中标识切面则显得凌乱、模糊。
在什么情况下使用注解形式的AOP?或者说使用注解来实现AOP有哪些优点呢?
1. XML风格的AOP仅仅支持"singleton"切面实例模型,而采用AspectJ风格的AOP则
没有这个限制。
2.XML风格的AOP中是不支持命名连接点的声明,而采用AspectJ风格的AOP则没有这个限制。不太理解的看下面实例代码:
在@AspectJ风格中我们可以编写如下的内容:
<span style="font-size:18px;"> @Pointcut(execution(* get*()))
public void propertyAccess() {} @Pointcut(execution(org.xyz.Account+ *(..))
public void operationReturningAnAccount() {} @Pointcut(propertyAccess() && operationReturningAnAccount())
public void accountPropertyAccess() {} </span>
在XML风格中,我们不能使用'&&'字符来连接命名连接点,如下:
<span style="font-size:18px;"> <aop:pointcut id="propertyAccess"
expression="execution(* get*())"/> <aop:pointcut id="operationReturningAnAccount"
expression="execution(org.xyz.Account+ *(..))"/>
<!-- 错误的配置 -->
<aop:pointcut id="accountPropertyAccess"
expression="propertyAccess && operationReturningAnAccount"/> </span>
注意: XML风格AOP虽然不支命名连接点的声明,但是,可以使用如下形式处理,如下配置:
<span style="font-size:18px;"> <aop:pointcut id="propertyAccess"
expression="execution(* get*())"/>
<aop:pointcut id="operationReturningAnAccount"
expression="execution(org.xyz.Account+ *(..))"/>
<aop:pointcut id="accountPropertyAccess"
expression="execution(* get*()) and execution(org.xyz.Account+ *(..))"/> </span>
总结
这两种方法都实现了AOP,提高了我们的程序代码复用率,很好的体现了抽象带来的好处,两者相互补充,相互借鉴,我们根据实际情况适当的选取和决策,在系统开发环境下适合开发的流程才是最重要的,
SSH深度历险(十一) AOP原理及相关概念学习+xml配置实例(对比注解方式的优缺点)的更多相关文章
- SSH深度历险(十) AOP原理及相关概念学习+AspectJ注解方式配置spring AOP
AOP(Aspect Oriented Programming),是面向切面编程的技术.AOP基于IoC基础,是对OOP的有益补充. AOP之所以能得到广泛应用,主要是因为它将应用系统拆分分了2个部分 ...
- SSH深度历险(二) Jboss+EJB的第一个实例
学习感悟:每次学习新的知识,都会通过第一个小的实例入手,获得成就感,经典的Hello Workd实例奠定了我们成功的大门哈,这些经典的实例虽小但是五脏俱全呢,很好的理解了,Ejb的核心. 今天主要以这 ...
- SSH深度历险(七) 剖析SSH核心原理(一)
接触SSH有一段时间了,但是对于其原理,之前说不出来莫模模糊糊(不能使用自己的语言描述出来的就是没有掌握),在视频和GXPT学习,主要是实现了代码,一些原理性的内容还是欠缺的,这几天我自己也一直在反问 ...
- SSH深度历险(六) 深入浅出----- Spring事务配置的五种方式
这对时间在学习SSH中Spring架构,Spring的事务配置做了详细总结,在此之间对Spring的事务配置只是停留在听说的阶段,总结一下,整体把控,通过这次的学习发觉Spring的事务配置只要把思路 ...
- SSH深度历险(九) Struts2+DWZ+Uploadify实现多文件(文件和图片等等)上传
在gxpt_uas系统中,要实现文件(文件和图片等等,可以灵活配置)的批量上传至mongodb,在学习这个过程中,学习了mongodb,并实现了批量上传的功能,实现思路:在DWZ的基础上参考官方的实例 ...
- Spring AOP基于xml配置实例
SpringAOP里的几个术语,什么切面,切点之类的,官方的说明太抽象.为了更好地理解记忆,这里几下我自己的通俗的理解. 切面:就是日记类,什么前置通知后置通知(这些都是所谓的Advice)的具体方法 ...
- Spring MVC 中使用AOP 进行统一日志管理--XML配置实现
1.介绍 上一篇博客写了使用AOP进行统一日志管理的注解版实现,今天写一下使用XML配置实现版本,与上篇不同的是上次我们记录的Controller层日志,这次我们记录的是Service层的日志.使用的 ...
- Spring Aop(七)——基于XML配置的Spring Aop
转发:https://www.iteye.com/blog/elim-2396043 7 基于XML配置的Spring AOP 基于XML配置的Spring AOP需要引入AOP配置的Schema,然 ...
- SSH深度历险(八) 剖析SSH核心原理+Spring依赖注入的三种方式
在java开发中,程序员在某个类中需要依赖其它类的方法,则通常是new一个依赖类再调用类实例的方法,这种开发存在的问题是new的类实例不好统一管理,spring提出了依赖注入的思想,即依 ...
随机推荐
- HDU 5506(GT and set)
题意: 表示看了很久,然而发现还是没看懂题. 正解:给你a个集合,让你把他们合并成k个,当两个集合有公共数字时可以合并. (一直以为是合并后,每个集合至少有两个数字相同- -,这英语也是醉了) 思路: ...
- 杜教筛进阶+洲阁筛讲解+SPOJ divcnt3
Part 1:杜教筛进阶在了解了杜教筛基本应用,如$\sum_{i=1}^n\varphi(i)$的求法后,我们看一些杜教筛较难的应用.求$\sum_{i=1}^n\varphi(i)*i$考虑把它与 ...
- Python中模块之xml的讲解
xml模块的功能介绍 这里主要讲解xml模块下的etree.ElementTree类. 1. 创建 具体代码如下 import xml.etree.ElementTree as XM namelist ...
- Python之作业购物车
作业之购物车优化 购物车优化要求如下: 用户入口: 启动程序后,输入用户名密码后,如果是第一次登录,让用户输入工资,然后打印商品列表 允许用户根据商品编号购买商品 用户选择商品后,检测余额是否够,够就 ...
- jqGrid 使用心得
参考: https://blog.csdn.net/u012411219/article/details/51315419 https://www.cnblogs.com/kissdodog/p/38 ...
- Mybatis Generator 代码生成配置
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE generatorConfiguration ...
- 原生JS实现圆周运动
<body> <div id="ball" style="width:20px; height:20px; background:red; border ...
- 全局变量&局部变量,global&nonlocal
###全局变量与局部变量 1.函数内部的变量名如果第一次出现,且出现在=前面,即被视为定义一个局部变量,不管全局域中有没有用到该变量名,函数中使用的将是局部变量 2.函数内部的变量名如果第一次出现,且 ...
- 深入理解Oracle中的随机函数
--Oracle中取随机值的函数 .dbms_random包 dbms_random包提供了一系列的随机值获取函数以及相关存储过程.下面详细讲解常用的函数和过程. ()dbms_random.rand ...
- Node.js 集群
稳定性: 2 - 不稳定 单个 Node 实例运行在一个线程中.为了更好的利用多核系统的能力,可以启动 Node 集群来处理负载. 在集群模块里很容易就能创建一个共享所有服务器接口的进程. var c ...