在Intellij上面导入项目 & AOP示例项目 & AspectJ学习 & Spring AoP学习
为了学习这篇文章里面下载的代码:http://www.cnblogs.com/charlesblc/p/6083687.html
需要用Intellij导入一个已有工程。源文件原始内容也可见:link
选择 Import Project -> "Create Project from existing sources" ->选择root目录,一步步选择完毕。
为了从百度maven服务器更快的下载,在pom.xml最下面加上以下repo地址:
<repositories>
<repository>
<id>nexus-public</id>
<url>http://maven.scm.baidu.com:8081/nexus/content/groups/public</url>
</repository>
<repository>
<id>nexus-public-snapshots</id>
<url>http://maven.scm.baidu.com:8081/nexus/content/groups/public-snapshots</url>
</repository>
</repositories>
然后可能需要在报错的文件里用 option+enter进行一些错误的更正。
然后在project structure里面进行一些artifact的添加,就可以生成JAR。
一直在报错找不到依赖文件。看了一下 Project里面有两个module,删掉其中的main,只留aop。然后就不再报错啦。。。
然后看例子。
demo4
CGLib 动态代理
我们使用开源的 CGLib 类库可以代理没有接口的类,这样就弥补了 JDK 的不足。
demo7
抛出异常AOP
Hello! Jack
---------- Throw Exception ----------
Target Class: aop.demo7.GreetingImpl
Method Name: sayHello
Exception Message: Error
-------------------------------------
Exception in thread "main" java.lang.RuntimeException: Error
...... Process finished with exit code
demo8
Spring AOP:引入增强
以上提到的都是对方法的增强,那能否对类进行增强呢?用 AOP 的行话来讲,对方法的增强叫做 Weaving(织入),而对类的增强叫做 Introduction(引入)。而 Introduction Advice(引入增强)就是对类的功能增强,它也是 Spring AOP 提供的最后一种增强。
@Component
public class GreetingIntroAdvice extends DelegatingIntroductionInterceptor implements Apology { public void saySorry(String name) {
System.out.println("Sorry! " + name);
} @Override
public Object invoke(MethodInvocation invocation) throws Throwable {
return super.invoke(invocation);
}
}
然后在spring的配置文件里面这样配:
<bean id="greetingProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="interfaces" value="aop.demo8.Apology"/>
<property name="target" ref="greetingImpl"/>
<property name="interceptorNames" value="greetingIntroAdvice"/>
<property name="proxyTargetClass" value="true"/>
</bean>
需要注意 proxyTargetClass 属性,它表明是否代理目标类,默认为 false,也就是代理接口了,此时 Spring 就用 JDK 动态代理。如果为 true,那么 Spring 就用 CGLib 动态代理。这简直就是太方便了.
9. Spring AOP:切面
配置如下:
<bean id="greetingAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
<property name="advice" ref="greetingAroundAdvice"/>
<property name="pattern" value="aop.demo9.GreetingImpl.good.*"/>
</bean> <bean id="greetingProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="target" ref="greetingImpl"/>
<property name="interceptorNames" value="greetingAdvisor"/>
<property name="proxyTargetClass" value="true"/>
</bean>
10. Spring AOP:自动代理(扫描 Bean 名称)
<bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
<property name="beanNames" value="*Impl"/>
<property name="interceptorNames" value="greetingAroundAdvice"/>
<property name="optimize" value="true"/>
</bean>
通过以上配置,就可以自动扫描bean进行匹配。
以上使用 BeanNameAutoProxyCreator 只为后缀为“Impl”的 Bean 生成代理。
需要注意的是,这个地方我们不能定义代理接口,也就是 interfaces 属性,因为我们根本就不知道这些 Bean 到底实现了多少接口。
此时不能代理接口,而只能代理类。所以这里提供了一个新的配置项,它就是 optimize。若为 true 时,则可对代理生成策略进行优化(默认是 false 的)。
也就是说,如果该类有接口,就代理接口(使用 JDK 动态代理);如果没有接口,就代理类(使用 CGLib 动态代理)。
而并非像之前使用的 proxyTargetClass 属性那样,强制代理类,而不考虑代理接口的方式。可见 Spring AOP 确实为我们提供了很多很好地服务。
11. Spring AOP:自动代理(扫描切面配置)
如果既要自动扫描bean,并且匹配方法,可以用下面的
<bean id="greetingAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
<property name="pattern" value="aop.demo11.GreetingImpl.good.*"/>
<property name="advice" ref="greetingAroundAdvice"/>
</bean> <bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator">
<property name="optimize" value="true"/>
</bean>
但是匹配的时候,还是有一些问题。很麻烦。
在 Spring 配置文件中,仍然会存在大量的切面配置。然而在有很多情况下 Spring AOP 所提供的切面类真的不太够用了,
比如:想拦截指定注解的方法,我们就必须扩展 DefaultPointcutAdvisor 类,自定义一个切面类,然后在 Spring 配置文件中进行切面配置。
不做不知道,做了您就知道相当麻烦了。
12. Spring + AspectJ(基于注解:通过 AspectJ execution 表达式拦截方法)
主要代码如下:
@Aspect
@Component
public class GreetingAspect { @Around("execution(* aop.demo12.GreetingImpl.*(..))")
public Object around(ProceedingJoinPoint pjp) throws Throwable {
before();
Object result = pjp.proceed();
after();
return result;
} private void before() {
System.out.println("Before");
} private void after() {
System.out.println("After");
}
}
下面重点来分析一下这个切点表达式:
execution(* aop.demo.GreetingImpl.*(..))
execution():表示拦截方法,括号中可定义需要匹配的规则。
第一个“*”:表示方法的返回值是任意的。
第二个“*”:表示匹配该类中所有的方法。
(..):表示方法的参数是任意的。
XML配置内容:
<context:component-scan base-package="aop.demo"/> <aop:aspectj-autoproxy proxy-target-class="true"/>
需要注意的是 proxy-target-class="true" 属性,它的默认值是 false,默认只能代理接口(使用 JDK 动态代理),当为 true 时,才能代理目标类(使用 CGLib 动态代理)。
13. Spring + AspectJ(基于注解:通过 AspectJ @annotation 表达式拦截方法)
首先用annotation定义一个tag
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; @Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Tag {
}
然后针对这个tag来写增强方法:
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component; @Aspect
@Component
public class GreetingAspect { @Around("@annotation(aop.demo13.Tag)")
public Object around(ProceedingJoinPoint pjp) throws Throwable {
before();
Object result = pjp.proceed();
after();
return result;
} private void before() {
System.out.println("Before");
} private void after() {
System.out.println("After");
}
}
最后,在方法上面打上tag就可以了:
@Component
public class GreetingImpl implements Greeting { @Tag
public void sayHello(String name) {
System.out.println("Hello! " + name);
}
}
除了 @Around 注解外,其实还有几个相关的注解,稍微归纳一下吧:
@Before:前置增强
@After:后置增强
@Around:环绕增强
@AfterThrowing:抛出增强
@DeclareParents:引入增强
此外还有一个 @AfterReturning(返回后增强),也可理解为 Finally 增强,相当于 finally 语句,它是在方法结束后执行的,也就说说,它比 @After 还要晚一些。
最后一个 @DeclareParents 竟然就是引入增强!为什么不叫做 @Introduction 呢?我也不知道为什么,但它干的活就是引入增强。
14. Spring + AspectJ(引入增强)
首先要定义一个aspect类:
@Aspect
@Component
public class GreetingAspect { @DeclareParents(value = "aop.demo14.GreetingImpl", defaultImpl = ApologyImpl.class)
private Apology apology;
}
在这个接口上标注了 @DeclareParents 注解,该注解有两个属性:
value:目标类
defaultImpl:引入接口的默认实现类
然后在实现一个ApologyImpl类:
package aop.demo14; public class ApologyImpl implements Apology { public void saySorry(String name) {
System.out.println("Sorry! " + name);
}
}
从 Spring ApplicationContext 中获取 greetingImpl 对象(其实是个代理对象),可转型为自己静态实现的接口 Greeting,也可转型为自己动态实现的接口 Apology,切换起来非常方便。
使用 AspectJ 的引入增强比原来的 Spring AOP 的引入增强更加方便了,而且还可面向接口编程(以前只能面向实现类),这也算一个非常巨大的突破。
上面这一句指的是如下,可以直接转型为Greeting,而不需要转型为GreetingImpl这个类了
public class Client { public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("aop/demo14/spring.xml");
Greeting greeting = (Greeting) context.getBean("greetingImpl");
greeting.sayHello("Jack"); Apology apology = (Apology) greeting;
apology.saySorry("Jack");
}
}
15. Spring + AspectJ(基于配置)
仍然还是有用户不能尝试这些特性,因为他们还在使用 JDK 1.4(根本就没有注解这个东西),怎么办呢?没想到 Spring AOP 为那些遗留系统也考虑到了。
demo15基本完全基于配置,因为代码很简单:
package aop; public interface Greeting { void sayHello(String name);
}
而配置会复杂一些:
<bean id="greetingImpl" class="aop.demo15.GreetingImpl"/> <bean id="greetingAspect" class="aop.demo15.GreetingAspect"/> <aop:config>
<aop:aspect ref="greetingAspect">
<aop:around method="around" pointcut="execution(* aop.demo15.GreetingImpl.*(..))"/>
</aop:aspect>
</aop:config>
使用 <aop:config> 元素来进行 AOP 配置,在其子元素中配置切面,包括增强类型、目标方法、切点等信息。
无论您是不能使用注解,还是不愿意使用注解,Spring AOP 都能为您提供全方位的服务。
下面这张图非常好。
给一张牛逼的高清无码思维导图,总结一下以上各个知识点:
再来一张表格,总结一下各类增强类型所对应的解决方案:
增强类型 | 基于 AOP 接口 | 基于 @Aspect | 基于 <aop:config> |
Before Advice(前置增强) | MethodBeforeAdvice | @Before | <aop:before> |
AfterAdvice(后置增强) | AfterReturningAdvice | @After | <aop:after> |
AroundAdvice(环绕增强) | MethodInterceptor | @Around | <aop:around> |
ThrowsAdvice(抛出增强 | ThrowsAdvice | @AfterThrowing | <aop:after-throwing> |
IntroductionAdvice(引入增强) | DelegatingIntroductionInterceptor | @DeclareParents | <aop:declare-parents> |
最后给一张 UML 类图描述一下 Spring AOP 的整体架构:
代码位置:/Users/baidu/Documents/Data/Work/Code/Demo_Code/aop_demo/
(完)
在Intellij上面导入项目 & AOP示例项目 & AspectJ学习 & Spring AoP学习的更多相关文章
- Spring 学习——Spring AOP——AOP配置篇Advice(有参数传递)
声明通知Advice 配置方式(以前置通知为例子) 方式一 <aop:config> <aop:aspect id="ikAspectAop" ref=" ...
- IntelliJ IDEA导入多个eclipse项目到同一个workspace下
IntelliJ IDEA 与eclipse在新建项目上工作区的叫法略有不同,区别见下图. 我们在eclipse都是在新建的workspace目录下新建我们的项目,但是在IDEA中没有workspac ...
- Intellij Idea 导入多个maven项目展示在左侧栏Maven Projects
刚刚要开始从eclipse切换成idea,据说idea功能强大,可是刚刚开始使用很多不习惯,导入第二个maven项目时之前的项目就没了,比较苦恼,下面介绍下导入多个maven项目展示在左侧栏Maven ...
- Intellij Idea 导入多个maven项目,通过父工程引入子工程
刚刚要开始从eclipse切换成idea,据说idea功能强大,可是刚刚开始使用很多不习惯,导入第二个maven项目时之前的项目就没了,比较苦恼,下面介绍下导入多个maven项目展示在左侧栏Maven ...
- spring-第十六篇之AOP面向切面编程之Spring AOP
1.上一篇介绍了AspectJ在AOP的简单应用,让我们了解到它的作用就是:开发者无需修改源代码,但又可以为这些组件的方法添加新的功能. AOP的实现可分为两类(根据AOP修改源码的时机划分): 1& ...
- 使用aspectJ实现Spring AOP的两种方式
方式一:基于aspectJ的XML配置 方式二:基于aspectJ的注解方式 基于aspectJ的XML配置 1) 引入相关jar包 2) 创建Spring核心配置文件,必须导 ...
- 基于@AspectJ配置Spring AOP之一--转
原文地址:http://tech.it168.com/j/2007-08-30/200708302209432.shtml 概述 在低版本Spring中定义一个切面是比较麻烦的,需要实现特定的接口,并 ...
- Spring 学习——Spring AOP——AOP配置篇Advice(无参数传递)
声明通知Advice 配置方式(以前置通知为例子) 方式一 <aop:config> <aop:aspect id="ikAspectAop" ref=" ...
- Spring 学习——Spring AOP——AOP配置篇Aspect、Pointcut
Schena——based AOP 声明 Spring所有的切面和通知器都必须放在一个<aop:config>标签内,可以同时配置多个<aop:config>元素. 每一个&l ...
随机推荐
- LA 3790 Overlapping Squares DFS
题意: 给出一个字符矩阵,问能否是不超过6个2×2的正方形组成的. 分析: 每次找一个最表面的正方形然后DFS就好了. 一个正方形被移开后,用一个特殊符号标记上,下次再匹配的时候就直接忽略这些位置. ...
- Java中String类通过new创建和直接赋值字符串的区别
方式一:String a = “aaa” ; 方式二:String b = new String(“aaa”); 两种方式都能创建字符串对象,但方式一要比方式二更优. 因为字符串是保存在常量池中的,而 ...
- jmeter进行dubbo接口测试
最近工作中接到一个需求,需要对一个MQ消息队列进行性能测试,测试其消费能力,开发提供了一个dubbo服务来供我调用发送消息. 这篇博客,介绍下如何利用jmeter来测试dubbo接口,并进行性能测试. ...
- niubi-job:一个分布式的任务调度框架设计原理以及实现
niubi-job的框架设计是非常简单实用的一套设计,去掉了很多其它调度框架中,锦上添花但并非必须的组件,例如MQ消息通讯组件(kafka等).它的框架设计核心思想是,让每一个jar包可以相对之间独立 ...
- spring AOP详解一
AOP是Aspect Oriented Programing的简称,面向切面编程.AOP适合于那些具有横切逻辑的应用:如性能监测,访问控制,事务管理以及日志记录.AOP将这些分散在各个业务逻辑中的代码 ...
- equals()和hashCode()方法在集合类set中的使用
Object的方法 equals()和hashCode() 是用来判断两个对象是否相等.基础类型判断是否相等时,使用“==”来判断,按java的说话,“==”当用来判断是基础类型是判断内容的,而引用对 ...
- 近期JS心得
child和tags都是[{id:1,value:'a'}]的格式,当点击一级标签,要看二级标签是否已经被选中,如果被选中,则清除出去 如果用for循环 再splice的话 当删除掉了一个元素后,数组 ...
- iOS----精品开源库-开发强力助攻
30个精品iOS开源库,超强助攻 你不会想错过他们,真的. 我爱开源. 文章的尾部你会看到一个太长不看的版本——一个简单的列表,只有标题和到项目的链接.如果你发现这篇文章是有用的,把它和你的iOS开 ...
- Welcome-to-Swift-21协议(Protocols)
协议定义了一个方法的蓝图,属性和其他适合特定任务或功能的要求.协议实际上并不提供一个这些要求的实现,它只是描述了一个实现会是什么样子.协议可以通过一个类,结构或枚举提供这些要求的具体实现.满足要求的任 ...
- HDU——1019Least Common Multiple(多个数的最小公倍数)
Least Common Multiple Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Ot ...