首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > 编程 >

spring入门常识总结4 AOP技术

2012-12-25 
spring入门知识总结4 AOP技术AOP技术1.引出问题建立? ? ? ? }? ? ? ? @Override? ? ? ? public void updat

spring入门知识总结4 AOP技术

AOP技术
1.引出问题
建立? ? ? ? }
? ? ? ? @Override
? ? ? ? public void update() {
? ? ? ? ? ? ? ? System.out.println("update method is called" + username);
? ? ? ? }
}
需求如下:如果实现类的username!=null,才可以调用save与update方法,为null则不能调用。当然要解决此问题,可以在save与update方法内部进行判断,但是如果在方法内部进行判断,代码则失去了灵活性,如果以后的需求改变,比如变成username.equals时,则又要在update/save方法中重新进行一次判断。如果save/update这样的方法很多,这样就会很麻烦。其实要解决此问题,可以通过<beans xmlns="http://www.springframework.org/schema/beans"
? ? ? ? xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
? ? ? ? xmlns:context="http://www.springframework.org/schema/context"
? ? ? ? xmlns:aop="http://www.springframework.org/schema/aop"
? ? ? ? xsi:schemaLocation="http://www.springframework.org/schema/beans? ?? ?? ?? ?http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
? ?? ?? ???http://www.springframework.org/schema/context? ?? ?? ???http://www.springframework.org/schema/context/spring-context-2.5.xsd
? ?? ?? ???http://www.springframework.org/schema/aop? ?? ?? ???http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">
? ? ? ? <aop:aspectj-autoproxy /><!-- 开启切面编程功能 -->
? ? ? ? <bean id="userDaoImp" />? ? ? ?
<bean id="theInterceptor"
? ? ? ? ? ? ? ? />
</beans>复制代码

说明:要想切面类起作用,首先要把切面类纳入spring容器管理。
步骤四、编写junit测试单元
? ? ? ? @Test
public void base() {
ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");? ? ? ? ? ? ? ?
? ? ? ? // UserDaoImp udii=(UserDaoImp) ctx.getBean("userDaoImp");
? ? ? ? UserDao ud = (UserDao) ctx.getBean("userDaoImp");
? ? ? ? System.out.println(ud.getClass().getName());
? ? ? ? ud.save();
}
说明:由于开启了切面编程功能,所以当我们获取一个被切面类监控管理的bean对象—UserDaoImp时,它实际上获取的是此对象的一个代理对象,而在spring中对代理对象的处理有如下原则:(1)如果要代理的对象实现了接口,则会按照Proxy的方式来产生代理对象,这即是说产生的代理对象只能是接口类型,比如起用上面注掉的代码就会报错,而且通过下面的打印语句我们也可以看出产生的是一个代理对象。(2)要代理的对象未实现接口,则按cglib方式来产生代理对象。??另还要注意:要想spring的切面技术起作用,被管理的bean对象只能是通过spring容器获取的对象。比如这里如果直接new出UseDaoImp对象,则new出的对象是不能被spring的切面类监控管理。
补充:测试被代理对象未实现接口时,spring切面技术的应用。
步骤一、修改切面类TheInterceptor切入点为如下内容:
@Pointcut("execution (* com.asm.dao.impl.*.*(..))")? ? ? ?
说明:拦截impl包下的所有类所有方法
步骤二、在beans.xml中增加如下内容:
<bean id="userDaoImp2" />
步骤三、junit测试代码如下:
public void base2() {
? ? ? ? ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");
? ? ? ? UserDaoImp2 udi2 = (UserDaoImp2) ctx.getBean("userDaoImp2");
? ? ? ? System.out.println(udi2.getClass().getName());
? ? ? ? System.out.println(udi2.getClass().getSuperclass().getName());
? ? ? ? udi2.save();
}
说明:UseDaoImp2未实现任何接口,因此在spring中利用切面技术来管理此类使用的动态代理技术实质是cglib的动态代理方式,所以产生的代理对象实质是被代理对象的一个子类,通过上面的控制台打印语句可以看出。
? ? ? ? return "添加成功";
}
需求:获取调用add方法传递的参数。操作步骤如下:在切面类增加如下代码:
@Before("anyMethod() && args(name)")// 前置通知,只针对UseDaoImp的add方法
public void beforeAdd(String name) {
? ? ? ? System.out.println("前置通知:" + name);
}
说明:在前置通知的方法中有一个参数,然后再把此参数作为拦截条件(即是说拦截带有一个String类型参数的方法)。args的名字和beforeAdd方法参数名字相同。
测试代码:

}
说明:afterReturningRes方法的参数就是要返回的参数类型,returning标记的就是的结果,它的取值与该方法参数名相同。??测试代码同(4)。
(6)获取抛出的异常
切面类的增加如下代码:
@AfterThrowing(pointcut="anyMethod",throwing="e")
public void catchException(Exception e){
? ? ? ? System.out.println("获取抛出的异常:"+e);??
}
throwing的取值和方法的参数名相同,测试代码省略。
7. 通知应用实例(基于XML)
步骤一、复制TheInterceptorX类为TheInterceptorXML,并去掉所有注解。
步骤二、建立beansXML.xml配置文件,内容如下:

<bean id="aspectBean"
? ? ? ? />
<aop:config>
<aop:aspect id="asp" ref="aspectBean">? ???--声明一个切面类
? ? ? ? ? ? ? ? <aop:pointcut id="thecut"? ?? ?? ?? ?? ???--声明一个切入点
? ? ? ? ? ? ? ? expression="execution(* com.asm.dao.impl.UserDaoImp.*(..))" />
? ? ? ? ? ? ? ? <aop:after-returning pointcut-ref="thecut" method="afterReturningRes" returning="result" />
? ? ? ? ? ? ? ? <aop:around pointcut-ref="thecut" method="around"/>
? ? ? ? ? ? ? ? <aop:after-throwing pointcut-ref="thecut" method="catchException" throwing="e"/>? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
? ? ? ? ? ? ? ? <aop:after pointcut-ref="thecut" method="after" />
? ? ? ? ? ? ? ? <aop:before pointcut-ref="thecut" method="before" />
? ? ? ? </aop:aspect>
</aop:config>
测试代码如下:
public void advieeTest() {
? ? ? ? ? ? ? ? ApplicationContext ctx = new ClassPathXmlApplicationContext("beansXML.xml");
? ? ? ? ? ? ? ? UserDao ud=(UserDao) ctx.getBean("userDaoImp");
? ? ? ? ? ? ? ? ud.add("xxx");? ? ? ? ? ? ? ?
}复制代码

未解决问题:不能成功传参给前置通知。
8.解析切入点表达式
1.格式:execution(返回值 空格 方法选择)。两部分组成,中间一定要有空格。
返回值:可以是*,说明拦截任何方法。Java.lang.String(全名),拦截返回值为String类型的方法。 常用的实例如下:
方法选择:包名[类名].*()。设定要拦截的方法签名。


9.总结
面向切面的常见应用(如权限拦截)、spring的aop依赖两种方式实现代理(依被代理的对象是否实现接口而定)、通知概念、基于注解与基于XML两种方式来配置切面、基本步骤(依要拦截的方法来设定切入点,依据业务需求实现拦截通知代码,切面纳入spring容器管理,要被监控的类只能是通过Spring容器获取)、切入点的格式。

热点排行