`
bolide74
  • 浏览: 84187 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

Spring温故知新(八)静态切入点和CGLIB代理,更智能、更方便!

阅读更多
前面一章我们利用了Spring的AOP框架实现了WALL-E自动送礼物的功能,但是没有实现筛选,而且每次都还得先写一个ISpeaker接口。对于一些小程序而言其实每次都必须要先实现一个接口是比较啰嗦的步骤,那么首先我们来看看怎么样才能省略掉定义接口这个步骤。

Spring的代理机制有两种,第一种就是前一篇实现的基于接口的代理,叫做JAVA动态代理。就像之前介绍的那样,它的原理是利用了java JDK自带的代理接口。
而另外一种就是CBLIB代理,它使用的就是CGLIB的代理功能。

那么要使用CGLIB代理,首先要做的就是导入CBLIB的依赖包:
spring-framework-2.5.6\lib\cglib\cglib-nodep-2.1_3.jar

接着让我们重写一个新的Robot类,我们就叫它WallE类吧
package com.iteye.bolide74.action;

public class WallE {
	public String name;

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public void say(String msg) {
		System.out.println("到达邻居家,对邻居说:" + msg + ",我是" + this.name);
	}

	public void clean() {
		System.out.println("开始进行垃圾回收程序");
	}
}

这里我们可以看到,这个WallE类是典型的POJO,没有实现任何接口,也没有继承父类!
为了充分的演示其他功能,我这里新加入了一个clean方法。

接着就是GetGift类和GiveGift类这两个Advice的实现代码,这跟上一章的代码一摸一样,可以直接沿用:
package com.iteye.bolide74.action;

import java.lang.reflect.Method;

import org.springframework.aop.MethodBeforeAdvice;

public class GetGift implements MethodBeforeAdvice {

	@Override
	public void before(Method arg0, Object[] arg1, Object arg2)
			throws Throwable {
		System.out.println("通过MethodBeforeAdvice接口获取了一个礼物!");
	}
}

package com.iteye.bolide74.action;

import java.lang.reflect.Method;

import org.springframework.aop.AfterReturningAdvice;

public class GiveGift implements AfterReturningAdvice {

	@Override
	public void afterReturning(Object arg0, Method arg1, Object[] arg2,
			Object arg3) throws Throwable {
		System.out.println("通过AfterReturningAdvice接口赠予了一个礼物!");
	}

}


紧接着就是最重要的config.xml这个Spring配置文件了:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
	<bean id="wallE" class="com.iteye.bolide74.action.WallE">
		<property name="name" value="Wall-E" />
	</bean>
	<bean id="getGift" class="com.iteye.bolide74.action.GetGift" />
	<bean id="giveGift" class="com.iteye.bolide74.action.GiveGift" />
	<bean id="giftProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
		<!-- 这个节点是关键,代表着开启CGLIB代理功能 -->
		<property name="proxyTargetClass" value="true" />
		<property name="target">
			<ref bean="wallE" />
		</property>
		<property name="interceptorNames">
			<list>
				<value>getGift</value>
				<value>giveGift</value>
			</list>
		</property>
	</bean>
</beans>

这里可以看到,CGLIB代理的区别,就在于giftProxy的property增加了一个proxyTargetClass,值为true。它就代表了开启CGLIB代理,如果事先没有导入CGLIB依赖包那么在运行应用代码的时候就会报错。

最后我们来看一下应用代码,这跟上一篇的应用代码也没有太大区别,除了多调用了一个clean方法:
package com.iteye.bolide74.tester;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.iteye.bolide74.action.WallE;

public class GiftBySpringTester {
	public static void main(String[] args) {		
		ApplicationContext actx = new ClassPathXmlApplicationContext(
				"config.xml");		
		WallE wallE = (WallE) actx.getBean("giftProxy");
		wallE.say("你好,CGLIB代理向你问候");
		System.out.println();
		wallE.clean();
	}
}

运行结果:
引用
通过MethodBeforeAdvice接口获取了一个礼物!
到达邻居家,对邻居说:你好,CGLIB代理向你问候,我是Wall-E
通过AfterReturningAdvice接口赠予了一个礼物!

通过MethodBeforeAdvice接口获取了一个礼物!
开始进行垃圾回收程序
通过AfterReturningAdvice接口赠予了一个礼物!


这时候大家可以看到,使用了CGLIB代理以后,虽然WallE类并没有实现接口,但还是能正常的被AOP代理,这就在开发一些小程序、或者在很多原本不实现接口,但是又需要用Spring来重构代码的时候带来很多便利。

CGLIB代理这里就差不多介绍完了,但是细心的同学会发现上面的运行结果里,WallE在执行clean方法的时候也被giftProxy代理了,打扫卫生的时候怎么会带上礼物呢?这明显是不合理的!那么有什么办法可以实现筛选功能,让WallE在say的时候带礼物,clean的时候不带礼物?没问题,接着看我们的下一个内容,静态切入点的实现:

我们只需要修改一下config.xml文件的内容,其他的都不用做改动:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
	<bean id="wallE" class="com.iteye.bolide74.action.WallE">
		<property name="name" value="Wall-E" />
	</bean>
	<bean id="getGift" class="com.iteye.bolide74.action.GetGift" />
	<bean id="giveGift" class="com.iteye.bolide74.action.GiveGift" />

	<!-- 新增两个Advisor -->
	<bean id="getGiftAdvisor"
		class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
		<property name="advice">
			<ref bean="getGift" />
		</property>
		<property name="patterns">
			<list>
		<!-- 这里使用的是正则表达式,代表了符合这个正则表达式的方法才会被代理 -->
				<value>.*say.*</value>
			</list>
		</property>
	</bean>
	<bean id="giveGiftAdvisor"
		class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
		<property name="advice">
			<ref bean="giveGift" />
		</property>
		<property name="patterns">
			<list>
				<value>.*say.*</value>
			</list>
		</property>
	</bean>

	<bean id="giftProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
		<property name="proxyTargetClass" value="true" />
		<property name="target">
			<ref bean="wallE" />
		</property>
		<property name="interceptorNames">
			<list>
	<!-- 这里的interceptorNames值换成了新增的两个Advisor,而不是直接用的Advice -->
				<value>getGiftAdvisor</value>
				<value>giveGiftAdvisor</value>
			</list>
		</property>
	</bean>
</beans>


我们重新执行一下上面的应用代码就可以看到以下的运行结果:
引用
通过MethodBeforeAdvice接口获取了一个礼物!
到达邻居家,对邻居说:你好,CGLIB代理向你问候,我是Wall-E
通过AfterReturningAdvice接口赠予了一个礼物!

开始进行垃圾回收程序


这就是Spring AOP的静态切入点的实现,它的原理就是把切入点的所有方法根据方法名进行筛选,符合指定正则表达式的方法才会被代理。
既然有静态切入点,那么相对的自然就有动态切入点。动态切入点略有不同,它不是通过方法名称来进行筛选,而是通过方法的实参的值来进行筛选。

由于使用动态切入点的话每次执行切入点的方法都会判断一次它的实参,效率比较低下;而静态切入点只需首次执行就会被缓存,以后都不用重复判断。因此在实际使用当中大部分还是用的静态切入点,只有在某些特殊情况才会用到动态切入点。

如果有兴趣的话可以另外搜索一下动态切入点的实现方法,这里就不重复了。



下一篇:Spring温故知新(九)Spring自动代理http://bolide74.iteye.com/blog/1049935
上一篇:Spring温故知新(七)Advice通知的5种类型 http://bolide74.iteye.com/blog/1038865
2
3
分享到:
评论
1 楼 bolide74 2011-05-18  
沉的可真快啊。。   消灭0回复~

相关推荐

    Spring温故知新六AOP向切面程

    【Spring AOP 向切面编程详解】 ...通过代理模式和切面编程,我们可以更灵活地控制代码执行的流程,而不必在多个地方重复相同的逻辑。这在大型项目中尤为重要,因为它可以减少代码冗余,提高开发效率。

    spring_2021.7.14.zip

    标题中的"spring_2021.7.14.zip"表明这是一份关于Spring框架的资料,时间戳为2021年7月14日,可能包含了该日期前后的学习或项目经验总结。描述中提到是"项目源码笔记",适合"入门级别或者复习用",意味着这份资料...

    Spring全家桶思维导图

    Spring框架是Java开发中的核心组件,它以其模块化、易用性和灵活性著称。"Spring全家桶"这一术语,指的是Spring生态系统中的一系列相互关联的项目和技术,它们共同构成了一个全面的企业级应用开发解决方案。本思维...

    springcloud视频学习6-2

    5. **Spring Cloud Config配置中心**:Config是SpringCloud提供的分布式配置管理工具,它可以集中管理和推送应用的配置,支持配置的实时更新,方便在分布式环境中管理配置。 6. **Spring Cloud Bus**:Spring Cloud...

    spring cloud + openshift

    spring cloud + openshift example

    spring cloud config

    Spring Cloud Config 是一个用于分布式系统配置管理的框架,它允许开发者在远程服务器上集中管理和版本化应用的配置,而不是在每个应用本地存储配置。这种方式在微服务架构中尤其有用,因为多个独立的服务需要共享和...

    温故知新ASP.NET 2.0(C#)

    1. **控件生命周期**:ASP.NET 2.0提供了更清晰的控件生命周期管理,使开发者能够更好地理解页面和控件的加载、初始化和回发过程。 2. **母版页(Master Pages)**:母版页允许开发者创建统一的网站布局,简化了...

    Spring注解大全,常用,随时查看,学习

    常用的spring注解大全,适合新手学习、老手温故知新。读懂spring,平步青云。

    行业报告---温故知新,从 4G 看 5G.zip

    行业报告“温故知新,从4G看5G”为我们揭示了移动通信技术从4G到5G的演进历程、技术变革及其对社会经济的深远影响。这份报告深入探讨了5G的关键特性,包括超高速率、低延迟、大规模连接以及网络切片等,这些都是5G...

    初中语文文学讨论现当代文学温故知新

    初中语文文学讨论现当代文学温故知新

    中信建设温故知新,从 4G 看 5G.rar

    《中信建设温故知新,从 4G 看 5G》这份资料主要探讨了移动通信技术从第四代(4G)到第五代(5G)的演进过程,以及这一演变带来的技术创新和产业影响。4G 和 5G 作为两个重要的通信时代,它们之间的差异和联系构成了...

    jsp,servlet,filter温故知新

    本文将深入探讨这些技术,帮助开发者温故知新,理解它们的功能、工作原理以及如何在实际项目中应用。 ### JSP(JavaServer Pages) JSP是一种动态网页技术,它允许开发者在HTML页面中嵌入Java代码,以实现动态内容...

    中信建设温故知新,从 4G 看 5G.pdf

    中信建设温故知新,从 4G 看 5G.pdf

    20210202-银河证券-“温故知新”系列之工业机器人行业复盘(二):从美国汽车行业“2mm工程”看工业机器人国产化空间.pdf

    工业机器人是现代制造业中不可或缺的重要组成部分,其发展水平是衡量一个国家制造业自动化、智能化程度的重要标志。本文档探讨了工业机器人在汽车行业中的应用,并结合美国汽车行业历史上的“2mm工程”,分析了工业...

    温故知新,通过学习尚学堂飞机游戏项目,理解Java语言基础知识.zip

    在本项目"温故知新,通过学习尚学堂飞机游戏项目,理解Java语言基础知识.zip"中,我们可以深入探讨Java编程语言的基础知识,并结合实际的游戏开发经验来加深理解。这是一个非常适合初学者或者想要巩固Java基础的...

    机械军工行业:“温故知新”系列之工业机器人行业复盘(二):从美国汽车行业“2mm工程”看工业机器人国产化空间.pdf

    从给定文件中提取的知识点如下: 1. 工业机器人行业概述:工业机器人是机械工程中的一种高科技自动化设备,主要应用于汽车制造、电子电器、化学橡胶塑料、金属制品、食品制造等多个行业。根据国际机器人联合会(IFR...

    datafun人工智能与大数据202109月刊.pdf

    - 成为DataFun会员可以享受直播回放、视频解锁、资料下载、身份特权等服务,便于技术选型、温故知新、借鉴经验和解决问题。 - 会员还能获得与专家和同行交流的机会,获取原创技术文章合集,并有机会参与内推招聘,...

    数学:吃透课本温故知新.docx

    在准备高考或其他重要考试的过程中,数学复习是一项至关重要的任务。要高效地复习数学,考生...在这个过程中,不仅要掌握知识,更要培养解决问题的技巧和独立思考的能力。只有这样,才能在考试中展现出优秀的数学素养。

    计算机小数表示.温故知新.pdf

    计算机小数表示是一种在计算机中表示小数的方法,分为定点表示法和浮点表示法两种。定点表示法是指小数点的位置固定不变,而浮点表示法是指小数点的位置可以浮动。浮点表示法可以表示更大的数值范围,但运算复杂性较...

Global site tag (gtag.js) - Google Analytics