spring已经实现了aop,为什么还要用aspectj
- spring已经实现了aop,为什么还要用aspectj
- AspectJ注解
- spring cache 怎么配置为aspectj
- 四,spring的aspectj注解有哪些,分别是什么意思
- spring aop,aspectj aop的实现原理分别是什么,两种aop的框架都支持哪些增强方法
- aspectj.jar 有什么用
- AspectJ如何实现AOP
- org.aspectj.lang 哪个包
- IntelliJ IDEA中AspectJ插件的安装及使用
spring有自己的AOP实现与aspectj的实现不同比较麻烦,马士兵的教程所讲的是spring整合了aspectj的AOP马士兵没有将spring自己的aop,在视频的末尾他说一般情况用不到spring自己的AOP你可以仔细听听,spring在做声明式事物处理时就没有用aspectj嘛!springAOP是设计用于在应用服务器环境下实现AOP,切入点与方面均由普通Java对象实现,其中连接点模型与AspectJ相同,只是远不如AspectJ丰富。针对你的问题spring有两组AOP一组是spring本身的一组是整合AspectJ,就好比在国际上一个中国人说英语是因为大家都说英语(好比AspectJ),但中国人还有自己的语言中文(spring自己的AOP)
aop注解
@Component 加入自定义通知类
@Service 加入服务层
@Aspect 声明切面,修饰切面类,获得通知.配合Component使用
注解开发通知
定义切入点
@PointCut ,修饰空方法 private void xxx(){} , 之后通过“方法名”获得切入点引用
在方法前加入注解通知类型:
@Before 前置 加入自定义方法前
@AfterReturning 后置(value=“myPoint()“,returning=“res“)
@Around 环绕
开发流程
第一步:开发注解的通知类 如下所示 我注释了 前置通知以及后置通知,根据自己的实际情况进行修改。
@Component(“AnnotationSLogAdvice“)
@Aspect
public class AnnotationSLogAdvice {
@Pointcut(“execution( * com.zyh.service.. . (..))“)
public void myPoint(){
}
/* @Before(“myPoint()“)
public void myBefore(JoinPoint joinPoint){
Log.info(“前置“);
} /
/ @AfterReturning(value = “myPoint()“ ,returning = “res“ )
public void myAfter(JoinPoint joinPoint, Object res){
Log.info(“后置“);
Log.info(“我是返回值:“+res);
}*/
}
第二步:开发目标接口和实现类(注解方式)
@Service(“AnnotationServiceImpl“)
public class AnnotationServiceImpl implements AnnotationService {
@Qualifier(“AnnotationDaoImpl“)
@Autowired
private AnnotationDaoImpl annotationDao;
@Override
public void add() {
annotationDao.addAnnotation();
}
}
第三步:开启注解扫描,开启Aspect
第四步: 测试
一次只开一种通知做测试,其他的通知先注释
@Test
public void testAnnotationBefore(){
ClassPathXmlApplicationContext classPathXmlApplicationContext=new ClassPathXmlApplicationContext(“applicationContext.xml“);
AnnotationService annotationService = (AnnotationService) classPathXmlApplicationContext.getBean(“AnnotationServiceImpl“);
annotationService.add();
}
@Test
public void testAnnotationAfter(){
ClassPathXmlApplicationContext classPathXmlApplicationContext=new ClassPathXmlApplicationContext(“applicationContext.xml“);
AnnotationService annotationService = (AnnotationService) classPathXmlApplicationContext.getBean(“AnnotationServiceImpl“);
annotationService.returnAnnotation();
}
@Test
public void testAnnotationAround(){
ClassPathXmlApplicationContext classPathXmlApplicationContext=new ClassPathXmlApplicationContext(“applicationContext.xml“);
AnnotationService annotationService = (AnnotationService) classPathXmlApplicationContext.getBean(“AnnotationServiceImpl“);
annotationService.add();
}
打印输出结果如下所示:
其他情况就不演示了。
spring AOP就是用aspectj来实现的,是依赖关系!AspectJ是动态代理的一种实现!而spring默认使用的就是AspectJ来实现的动态代理,spring自己的AOP就是使用AspectJ来实现的!当然你也可以使用其他的实现,如cglib!
注解模式的aspectj中,切面逻辑、切入点等都需要集中定义在一个类中。其中:
@Pointcut注解定义了切入点,它通过一个execution表达式来指定需要切入的类和方法,将本注解所在的方法与切入的方法绑定,后续的操作中都直接使用注解所在方法的方法名来映射被切入的方法(因而本方法只需为空即可)。pointcut可定义多个
Aspectj提供了多种类型的切面逻辑:主要有@After(方法结束)、@AfterReturning(方法返回)、@AfterThrowing(方法抛出异常)、@Before(方法开始前)、@Around(方法前后)这五个针对方法的注入,以及其它一些针对变量声明的注入(不常用)
从注解的参数列表中可以看出该注解所对应的切面逻辑能提供什么样的参数,如:@AfterReturning的returning参数,可以指定目标方法的返回值在本切面逻辑中的变量名;@AfterThrowing的throwing参数,可以指定目标方法抛出的异常对象在本切面逻辑中的变量名。除此而外,所有的切面注解都必有两个参数:value和argNames,value用于指定pointcut的方法名,argNames则是目标方法各参数在本切面逻辑中的方法名
切面方法自带一个参数叫JoinPoint,其中保存了方法的一些元数据信息,最有用的便是可以从中直接获取参数对象列表,以及可以直接获取到作为注入点的目标对象
转自:?t.cn?/?R60H3R9
你好,别想的太难了,你可以参考一下底下:
1、使用基于注解的AOP事务管理
探索tx:annotation-driven标签:
标签是注解驱动的事务管理支持的核心。
标签的属性:
transaction-manager:指定到现有的PlatformTransactionManager bean的引用,通知会使用该引用。default=“transactionManager“
mode:指定Spring事务管理框架创建通知bean的方式。可用的值有proxy和aspectj。前者是默认值,表示通知对象是个JDK代理;后者表示Spring AOP会使用AspectJ创建代理。
order:指定创建的切面的顺序。只要目标对象有多个通知就可以使用该属性。
proxy-target-class:该属性如果为true就表示你想要代理目标类而不是bean所实现的所有接口。default=“false“
探索@Transactional注解:
你可以指定传播、隔离级别、超时以及允许和不允许的异常。
@Transactional注解的属性:
propagation:指定事务定义中使用的传播
isolation:设定事务的隔离级别
timeout:指定事务的超市(秒)
readOnly:指定事务的超时
noRollbackFor:目标方法可抛出的异常所构成的数组,但通知仍会提交事务
rollbackFor:异常所构成的数组,如果目标方法抛出了这些异常,通知就会回滚事务
基于注解的事务管理小结:
如果定义在类上,那么所有的方法都使用相同的方式,有些read就会抱怨给太多的东西了。
如果在每个方法上都定义注解,那么就会很麻烦。
(可以使用XML AOP事务管理能更好的处理这种情况)
2、使用XML AOP事务管理
标签,该标签会创建一个事务处理通知。
view plaincopy to clipboardprint?
或
《aop:pointcut id=“allServiceMethods“
expression=“execution(* com.apress.prospring2.ch16.services.*.*(..))“/》
《aop:advisor advice-ref=“defaultTransactionAdvice“
pointcut-ref=“allServiceMethods“/》
《tx:method
name=“*“
isolation=“DEFAULT“
propagation=“REQUIRED“
no-rollback-for=“java.lang.RuntimeException“
timeout=“100“/》
《tx:method
name=“get*“
read-only=“true“/》
3、tx:advice标签简介
id是该advice bean的标识,而transaction-manager则必须引用一个PlatformTransactionManager bean。
还可以通过标签定制标签所创建的通知的行为。
标签的属性:
name:方法名的匹配模式,通知根据该模式寻找匹配的方法。
propagation:设定事务定义所用的传播级别。
isolation:设置事务的隔离级别。
timeout:指定事务的超时(秒)。
read-only:该属性为true指示事务是只读的
no-rollback-for:以逗号分隔的异常类的列表,目标方法可以跑出这些异常而不会导致通知执行回滚
rollback-for:以逗号分隔的异常类的列表,当目标方法跑出这些异常时会导致通知执行回滚。默认情况下,该列表为空,因此不在no-rollback-for列表中的任何运行时异常都会导致回滚。
中isolation(隔离)和propagation(传播)参数的含义:
getIsolationLevel:他对其他事务所看到的数据变化进行控制。
事务隔离级别:
隔离级别 说明
ISOLATION_DEFAULT 默认级别(对大多数数据库来说就是ISOLATION_READ_COMMITTED)
ISOLATION_READ_UNCOMMITTED 最低的隔离级别。事实上我们不应该隔离级别,因为在事务完成前,其他事务可以看到该事务所修改的数据。而在其他事务提交前,该事务也可以看到其他事务所做的修改。
ISOLATION_READ_COMMITTED 大多数数据库的默认级别。在事务完成前,其他事务无法看到该事务所修改的数据。遗憾的是,在该事务提交后,你就可以查看其他事务插入活更新的数据。这意味着在事务的不同点上,如果其他事务修改数据,你会看到不同的数据。
ISOLATION_REPEATABLE_READ 该隔离级别确保如果在事务中查询了某个数据集,你至少还能再次查询到相同的数据集,即使其他事务修改了所查询的数据。然而如果其他事务插入了新数据,你就可以查询到该新插入的数据。
ISOLATION_SERIALIZABLE 代价最大、可靠性最高的隔离级别,所有的事务都是俺顺序一个接一个的执行。
getPropagationBehavior:指定了当代码请求一个新的事务时Spring所做的事情。
传播行为指:
传播行为 说明
PROPAGATION_REQUIRED 当前如果有事务,Spring就会使用该事务;否则会开始一个新事务。
PROPAGATION_SUPPORTS 当前如果有事务,Spring就会使用该事务;否则不会开启一个新事务。
PROPAGATION_MANDATORY 当前如果有事务,Spring就会使用该事务;否则会抛出异常。
PROPAGATION_REQUIRES_NEW Spring总会开始一个新事务。如果当前有事务,则该事务挂起。
PROPAGATION_NOT_SUPPORTED Spring不会执行事务中的代码。代码总是在非事务环境下执行,如果当期有事务,则该事务挂起。
PROPAGATION_NEVER 即使当前有事务,Spring也会在飞事务环境下执行。如果当前有事务,则抛出异常。
PROPAGATION_NESTED 如果当前有事务,则在嵌套事务中执行。如果没有,那么执行情况与PROPAGATION_REQUIRED一样。
望采纳!
在 eclipse 上下载个 AJDT 插件 (AspectJ Development Tools),然后创建一个样例项目体验一下先,你就可以在项目的属性中的 Java Build Path 中看到它吧。
它就是 AspectJ 的运行时支持库。
我们只需要提供两个不同的Aspect--认证Aspect和事务Aspect。 比如,我们有一个Bank(银行)类。Bank有两个方法,deposit(存钱)和withdraw(取钱)。 class Bank { public float deposit(AccountInfo account, float money){// 增加account账户的钱数,返回账户里当前的钱数 }public float withdraw(AccountInfo account, float money){// 减少account账户的钱数,返回取出的钱数 }} 这两个方法涉及到用户的账户资金等重要信息,必须要非常小心,所以编写完上面的商业逻辑之后,项目负责人又提出了新的要求--给Bank类的每个重要方法加上安全认证特性。 于是,我们不得不分别在上面的两个方法中加入安全认证的代码。 class Bank { public float deposit(AccountInfo account, float money){// 验证account是否为合法用户 // 增加account账户的钱数,返回账户里当前的钱数 }public float withdraw(AccountInfo account, float money){// 验证account是否为合法用户 // 减少account账户的钱数,返回取出的钱数 }}这两个方法都需要操作数据库,为了保持数据完整性,项目负责人又提出了新的要求--给Bank类的每个操作数据库的方法加上事务控制。 于是,我们不得不分别在上面的两个方法中加入安全认证的代码。 class Bank { public float deposit(AccountInfo account, float money){// 验证account是否为合法用户 // Begin Transaction// 增加account账户的钱数,返回账户里当前的钱数 // End Transaction}public float withdraw(AccountInfo account, float money){// 验证account是否为合法用户 // Begin Transaction// 减少account账户的钱数,返回取出的钱数 // End Transaction}}我们看到,这些与商业逻辑无关的重复代码遍布在整个程序中。实际的工程项目中涉及到的类和函数,远远不止两个。如何解决这种问题? 我们首先来看看OOP能否解决这个问题。 我们利用Design Pattern的Template Pattern,可以抽出一个框架,改变上面的例子的整个设计结构。 abstract class Base {public float importantMethod(AccountInfo account, float money){// 验证account是否为合法用户 // Begin Transactionfloat result = yourBusiness(account, money)// End Transactionreturn result;}protected abstract float yourBusiness(AccountInfo account, float money);}class BankDeposit extends Base{protected float yourBusiness(AccountInfo account, float money){// 增加account账户的钱数,返回账户里当前的钱数 }};class BankWithdraw extends Base{protected float yourBusiness(AccountInfo account, float money){// 减少account账户的钱数,返回取出的钱数 }};这里我们用一种很勉强的方法实现了认证和事务代码的重用。而且,有心的读者可能会注意到,这种方法的前提是,强制所有的方法都遵守同样的signature。 如果有一个转账方法transfer(AccountInfo giver, AccountInfo receiver, float money),由于transfer方法的signature不同于yourBusiness的signature,这个方法无法使用上面的框架。 这个例子中提到的认证,事务等方面,就是AOP所关心的Aspect。 AOP就是为了解决这种问题而出现的。AOP的目的就是-- Separation of Concernshttps://www.bjygyt.com/hynews// 验证account是否为合法用户 return proceed();}}aspect TransactionAspect { pointcut bankMethods() : execution(* Bank.deposit(…)) || execution (* Bank. withdraw (…));Object around(): bankMethods(){// Begin TransactionObject result = proceed();return result;}}我们用AspectJ编译器编译Bank文件和含有aspect的这个文件,出来的结果就是带有安全认证和事务处理的Bank类。编译出来的这个Bank类调用了AspectJ Runtime Lib,所以,如果你要运行这个Bank类,你需要把AspectJ Runtime Lib设置在你的classpath里面。 我们来看看,AspectJ编译器为我们做了什么事情。1. 首先,AspectJ从文件列表里取出所有的文件名,然后读取这些文件,进行分析。2. AspectJ发现一些文件含有aspect的定义,在这个例子里,就是AuthAspect和TransactionAspect的定义;这些aspect就是代码生成规则。3. AspectJ根据这些aspect代码生成规则,修改添加你的源代码。在这个例子里,就是修改添加Bank文件。4. AspectJ读取AuthAspect的定义,发现了一个pointcut--bankMethods();这个pointcut的定义是execution(* Bank.deposit(…)) || execution(* Bank. withdraw (…)),表示所有对Bank类的deposit和withdraw方法的执行点。5. AspectJ继续读取AuthAspect的定义,发现了一个around(),这在AspectJ中叫做Advice,Advice允许你在某个类的方法的调用之前或调用之后,加入另外的代码。所示代码中的around()的“ // 验证account是否为合法用户“部分,就是要加入的代码。这段代码要加在哪里呢?around()后面跟了一个pointcut--bankMethods()。根据这个pointcut,AspectJ会把这段代码加入到Bank.deposit和Bank.withdraw两个方法的执行之前。6. AspectJ读取TransactionAspect的定义,象第(4)步一样,发现了发现了一个pointcut--bankMethods()。AspectJ继续读取AuthAspect的定义,发现了一个around()。
org.aspectj.lang是AspectJ的包。
AspectJ使用 org.aspectj.lang.JoinPoint 接口表示目标类连接点对象,如果是环绕增强,则使用 org.aspectj.lang.ProceedingJoinPoint 表示连接点对象,ProceedingJoinPoint 类是 JoinPoint 的子接口。
缺少jar包。自己一个一个的导入了一下就好了。
《dependency》?
《groupId》 org.aspectj《/groupId 》?
《artifactId》 aspectjweaver《/artifactId 》?
《version》 1.8.7《/version 》?
《/dependency》?
AspectJ:
AspectJ(也就是AOP)的动机是发现那些使用传统的编程方法无法很好处理的问题。考虑一个要在某些应用中实施安全策略的问题。
安全性是贯穿于系统所有模块间的问题,每个模块都需要应用安全机制才能保证整个系统的安全性,很明显这里的安全策略的实施问题就是一个横切关注点,使用传统的编程解决此问题非常的困难而且容易产生差错,这就正是AOP发挥作用的时候了。@AspectJ 使用了Java5 的注解,可以将切面声明为普通的Java类。
AspectJ是AOP的一种实现技术,IntelliJ IDEA是一款集成开发工具。在使用IntelliJ IDEA编写AspectJ代码之前需要本机先安装AspectJ,具体的安装步骤可以参考我的其他文章。AspectJ的功能类似于拦截器,这是一种切面技术,我们可以使用AspectJ切入满足切点规则的所有方法,并在方法的执行前后加一些通用的处理,下面跟着我一起去学习吧。
IntelliJ IDEA
首先我们打开IntelliJ IDEA开发工具,在菜单栏点击File--》Settings--》Plungins,进入到插件管理的页面。接下来我们在右侧的搜索框输入Aspect查询,下图在输入到Asp时便会模糊查询出结果,我们将AspectJ Support和Spring AOP/@AspectJ后面的方框勾选上即可。
接下来我们按住Ctrl+Shift+Alt+S,或者点击下图中所示的图标进入到Project Structure页面,点击Project Settings下方的Libraries,然后点击“+“号,最后选择Java,在接下来弹出的页面中选择aspectjrt.jar这个jar包。
接下来再回到Project Structure下方的Libraries设置,选择需要应用AspectJ的工程,然后点击“OK”按钮即可。
接下来进入到真正使用的部分了,我们首先创建一个Aspect切面,类似于创建一个类。在IntelliJ IDEA的菜单中点击“New”,新建一个Aspect。我们给这个切面取个名字MyAspectJ,注意下方的kind类别是Aspect,这里生成的aspectJ文件是.aj后缀的,而不是.class后缀的,这一点希望大家注意。
生成的aspectJ文件是.aj后缀的,所以原来的编译工具javac便不能使用了,因此我们需要修改编译工具。菜单栏点击File--》Settings--》搜索Compile,结构为Build,Execution,Deployment--》Compiler--》Java Compiler。我们右侧将Use Compiler修改为Ajc,在Path to Ajc compiler中选择安装目录下的aspectjtools.jar。
以上编译工具也设置完了,我们开始编写代码了。首先我们写一个入门的HelloWorld类,该类中有一个需要被AspectJ切面拦截的方法sayHello(),还有一个main方法用于执行程序。
然后我们再完善上面创建的MyAspectJ,创建pointcut切点,注意该写法是aspectJ特有的语法。pointcut表示定义的是一个切点,logPointCut()是切点的名字,call()里面是需要拦截的,* 标识返回值是任意类型,然后是类名.方法名(),..表示任意类型的参数。我们定义before()和after()这两个前置和后置拦截,分别用于在别拦截方法的前后执行。
最后在HelloWorld类执行main方法启动程序,我们看一下执行的结果,可以看到在sayHello()方法的执行前后分别执行了拦截。
.aj后缀的文件必须要使用Ajc的编译器,javac不可以编译。
相关tag:aspectj是什么
本站部分资源来源于网络,如果侵犯了您的权益,请联系我们删除1354090129@qq.com