《Java从入门到放弃》框架入门篇:spring中AOP的配置方式

spring中最核心的两个东东,一个IOC,一个AOP。

AOP(Aspect-OrientedProgramming)面向方面编程,也可以叫面向切面编程。

从一个新人的角度可以这样来理解:一般软件中的功能,我们可以分为两大类,一类是业务功能,一类是系统功能。

业务功能是指这个软件必须要用到的,没有的话客户就不给钱的。比如淘宝APP,如果你只能在上面浏览商品而不能购物,那就说明业务功能太监了···。

系统功能主要是指与业务无关,没有这块内容也不影响软件使用的。比如日志管理、权限处理等。

AOP主要用来做什么呢?就是用来很灵活的把系统功能配置到业务功能中去。比如这个博客系统,最开始为了赶进度,没有做相应的日志系统,同时游客也可以自由评论。现在已经上线后,需要对用户的操作都做日志记录,同时只允许登录用户访问。这就可以使用AOP来达到我们的目的。如下图所示:

Spring比较常用的增强

MethodBeforeAdvice:前置增强,表示在目标方法执行前实施增强。

AfterReturningAdvice:后置增强,表示在目标方法执行后实施增强。

MethodInterceptor:环绕增强,表示在目标方法执行前后实施增强。

ThrowsAdvice:抛出异常增强,表示在目标方法抛出异常后实施增强。

IntroductionInterceptor:引介增强,表示在目标类中添加一些新的方法和属性。

感觉解释这些概念真是费脑细胞 - -,还是直接来看代码吧。

接下来,我们完成一个简单案例:摄像头监控员工的动作(工作、打游戏、睡觉)。实现步骤如下:

1.1)创建员工类,包含三个方法(工作、打游戏、睡觉)

public class Employee {
	private String name;

	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	
	public void playGame(){
		System.out.println("偷偷玩游戏。");
	}
	public void playSleep(){
		System.out.println("偷偷睡会儿。");
	}
	public void working(){
		System.out.println("正在努力工作中···");
	}
}

1.2)创建三星摄像头类,实现前置增强来监控

public class SXCamera implements MethodBeforeAdvice {
    @Override
    public void before(Method arg0, Object[] arg1, Object arg2) throws Throwable {
	System.out.println("正在监控员工的行为...");
    }
}

1.3)在spring配置文件中注入员工对象和摄像头对象

<bean id="lidaye" class="com.pxy.entity.Employee">
    <property name="name" value="李大爷"></property>
</bean>
<bean id="sx250" class="com.pxy.entity.SXCamera"></bean>
<!-- 配置代理对象,来代理员工李大爷,同时注入了增强的功能 -->
<bean id="employee" class="org.springframework.aop.framework.ProxyFactoryBean"
	p:target-ref="lidaye" p:interceptorNames="sx250"></bean>

1.4)调用员工的三个方法,并查看显示结果(注意是得到的代理对象Bean)

public static void main(String[] args) {
    ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
    Employee li = applicationContext.getBean("employee", Employee.class);
    li.working();
    li.playGame();
    li.playSleep();
}

接下来,我们再配置一个后置增强,对于不工作的行为进行记录。代码如下,请Look:

1.5)添加华为摄像头类,实现了后置增强

public class HWCamera implements AfterReturningAdvice {
    @Override
    public void afterReturning(Object arg0, Method arg1, Object[] arg2, Object arg3) throws Throwable {
	Employee emp = (Employee)arg3;
	if(arg1.getName().toLowerCase().indexOf("game")>=0){
            System.out.println("发现员工("+emp.getName()+")正在打游戏,拍照记录!");
	}
        else if(arg1.getName().toLowerCase().indexOf("sleep")>=0){
            System.out.println("发现员工("+emp.getName()+")正在睡觉,拍照记录!");
	}
    }
}

1.6)修改spring配置文件,注入华为摄像头对象,并修改代理,加入后置增强

<!-- 配置华为摄像头(用来后置增强) -->
<bean id="hw500" class="com.pxy.entity.HWCamera"></bean>
<!-- 配置正则过滤对象,来过滤华为摄像头监控的行为 -->
<bean id="hw500Regexp" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor" p:advice-ref="hw500">
    <!-- 这儿的.*表示任意多个字符 -->
    <property name="pattern" value="com.pxy.entity.Employee.play.*"></property>
</bean>
<bean id="employee" class="org.springframework.aop.framework.ProxyFactoryBean"
    p:target-ref="lidaye" p:interceptorNames="sx250,hw500Regexp"></bean>

1.7)继续调用员工的方法(Test类的代码不变)并查看显示结果

可以发现,后置增强因为使用了正则来匹配Employee中的所有以play开头的方法,所以只对play开头的方法进行增强。

最最最最最后,还有更简单的办法,使用注解的方式来实现增强···,这种方式超级简单,推荐使用!!!

1.8)再次创建一个前置增强(注解方式实现),让员工在执行各种行为前喊一句:“毛主席万岁!”

@Aspect
public class ShoutAdvice {
    //*  表示一个由任意多个任意字符组成的元素,注意,只是一个元素
    //.. 表示任意多个元素
    //下面的字符串表示匹配 com.pxy.entity.Customer中所有方法,这个方法可以有任意多个参数,返回值为任意类型
    @Before("execution(* com.pxy.entity.Employee.*(..))")
    public void shout(){
        System.out.println("毛主席万岁!");
    }
}

1.9)在配置文件中注入喊口号对象,并开启自动代理注入(注意修改beans,引入AOP功能)

<beans
	xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:p="http://www.springframework.org/schema/p"
	xmlns:aop="http://www.springframework.org/schema/aop"
	xsi:schemaLocation="
	http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
	http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd"
>
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
<!-- 配置喊口号对象 -->
<bean id="shoutAdvice" class="com.pxy.entity.ShoutAdvice"></bean>
</beans>

1.10)修改getBean,直接得到“李大爷”对象(千万不要得到代理对象),并运行看结果

Employee li = applicationContext.getBean("lidaye", Employee.class);
li.working();
li.playGame();
li.playSleep();

好了,spring中的AOP入门就介绍到这儿,各位小伙伴再自己试试吧···

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏python3

python3--python的出生与应用

python的创始人为吉多·范罗苏姆(Guido van Rossum)。1989年的圣诞节期间,吉多·范罗苏姆(中文名字:龟叔)为了在阿姆斯特丹打发时间,决心...

1112
来自专栏mySoul

设计模式 开闭原则

软件实体应该对扩展开放,对修改关闭,即实体应当通过扩展实现变化,而不是修改代码实现变化

1141
来自专栏Python爬虫与算法进阶

爬虫之全站爬取方法

其实这个很好理解。比如说知乎,一个大V有100W粉丝,从这个大V出发,抓取粉丝的粉丝,一直循环下去。(可能是个死循环)

2343
来自专栏CSDN技术头条

十五条有用的Golang编程经验

本文作者在很短的时间内就从对Golang一无所知到开发出真正的产品。在学习Golang的过程中,他总结出十五条编程经验以分享给读者。以下是译文。 ? 像许多其他...

2928
来自专栏程序员互动联盟

【编程基础】聊聊如何学习Java——Java的特性

上一篇文章聊了学习编程可能会遇到的心里障碍和为什么学习Java,看了网友们的回复小编很激动,我会积极听取网友们的留言,在我以后的文章中改进。现在说Java语言的...

3719
来自专栏JAVA高级架构

Java设计模式-责任链模式

作者:Jet啟思 链接:https://juejin.im/post/5a126b146fb9a0450c490201 今天来说说程序员小猿和产品就关于需求发生...

37111
来自专栏Crossin的编程教室

【Python 第7课】if

感觉又一次被微信坑了。前两天刚说改变课程发送方式,今天微信就突然服务器升级,暂时不能新增接收文章的关键字了。所以这两天,还是用回老方式,直接推送。过去的课程0~...

2896
来自专栏阮一峰的网络日志

Javascript的10个设计缺陷

前几篇文章,我经常说Javascript的设计不够严谨,有很多失误。 今天的这一篇,前半部分就谈为什么会这样,后半部分将列举Javascript的10个设计缺陷...

3547
来自专栏java一日一条

为什么用 Java:一个 Python 程序员告诉你

说实话,本人刚开始的时候也是同样的反应。但是由于Java的类型安全,执行性能和坚如磐石的工具,我渐渐地开始欣赏Java。同时我注意到,现在的Java已今非昔比—...

611
来自专栏微信公众号:Java团长

Java基础05 实施接口

在Java基础04 封装与接口中,private关键字封装了对象的内部成员。经过封装,产品隐藏了内部细节,只提供给用户接口(interface)。

742

扫码关注云+社区