什么叫AOP
Aop术语叫做面向切面编程,是OOP的扩展和延伸,用来解决OOP遇到的问题。它被称作一种叫横切的技术,剖解开类的对象内部,并将那些影响了业务逻辑的相关代码封装起来形成一个可重用的组件模块,我们将它命名为切面,切面就是那些与业务无关,但是却被业务共同调用的代码,我们将它们封装起来,形成可重用的笔记,减少代码的重用,降低了代码之间的耦合度,便于可维护性和可操作性。
AOP的底层实现方式有两种,JDK动态代理和cglib动态代理,其中JDK动态代理只能应用于实现了接口的实现类,是Spring自带的实现方式,但是cglib相当于第三方的代理方式,即使没有实现接口也能实现代理。在spring具体代理底层实现不用自己掌握,Spring会根据实际情况自动切换,spring中是在配置文件中配置具体的代理。
AOP的应用有:日志记录,权限管理,性能检测等。
在应用之前还要了解AOP的相关术语:连接点:可以被拦截的点,就是可以被增强的那些方法。
切入点:具体被拦截的点
通知:前置通知、环绕通知、后置通知、异常抛出通知,最终通知
前置通知:比如说很多个dao层有一个相同的方法,突然一天这个方法需要先进行权限校验才能被执行,比如判断他是不是管理员,这时就在代理类里加一个权限校验的方法,用配置切面的方式配置到具体的方法上面,这样每次执行那个方法前都会先进行权限校验,这个方法就叫通知,在方法之前执行的这个代理方法就叫做前置通知
引介:类的增强(一般不会用到)
目标:被增强的对象(具体的增强类类)
织入:将增强应用到目标的过程
代理:织入增强后产生的对象
切面:切入点和通知的组合
具体的切面代码
**
* 切面类
*/
public class MyAspectJ {
/**
* 前置通知
*/
public void checkPri(JoinPoint joinPoint){
System.out.println("权限校验----"+joinPoint);
}
/**
* 后置通知
*/
public void writeLog(Object result){
System.out.println("日志记录------"+result);
}
/**
* 性能监控(环绕通知)
*/
public Object around(ProceedingJoinPoint joinPoint) throws Throwable{
System.out.println("环绕前通知----"+joinPoint);
Object obj = joinPoint.proceed();
System.out.println("环绕后通知----"+joinPoint);
return obj;
}
/**
* 异常抛出通知
*/
public void afterThrowing(Throwable ex){
System.out.println("异常抛出通知----"+ex.getMessage());
}
/**
* 最终通知,相当于finally代码块中的内容
*/
public void after(){
System.out.println("最终通知");
}
—配置文件代码—
<!--将切面类交给Spring管理-->
<bean id="productDao" class="com.heima.AopAspectJ.ProductDaoImpl"/>
<bean id="myaspectJ" class="com.heima.AopAspectJ.MyAspectJ"/>
<!--通过AOP的配置完成对目标类生成代理-->
<aop:config>
<!--表达式配置哪些类的哪些方法需要进行增强-->
<aop:pointcut expression="execution(* com.heima.AopAspectJ.ProductDaoImpl.*(..))" id="pointcut1"/><!--..就是任意函数的意思-->
<aop:pointcut expression="execution(* com.heima.AopAspectJ.ProductDaoImpl.delete(..))" id="pointcut2"/><!--..就是任意函数的意思-->
<aop:pointcut expression="execution(* com.heima.AopAspectJ.ProductDaoImpl.update(..))" id="pointcut3"/><!--..就是任意函数的意思-->
<aop:pointcut expression="execution(* com.heima.AopAspectJ.ProductDaoImpl.find(..))" id="pointcut4"/><!--..就是任意函数的意思-->
<!--配置切面-->
<aop:aspect ref="myaspectJ">
<!--前置通知-->
<aop:before method="checkPri" pointcut-ref="pointcut1"/>
<!--后置通知-->
<aop:after-returning method="writeLog" pointcut-ref="pointcut2" returning="result"/>
<!--最终通知叫aop:after-->
<!--环绕通知-->
<aop:around method="around" pointcut-ref="pointcut3"/>
<!--异常抛出通知-->
<aop:after-throwing method="afterThrowing" pointcut-ref="pointcut4" throwing="ex"/>
<!--最终通知-->
<aop:after method="after" pointcut-ref="pointcut4"/>
</aop:aspect>
</aop:config>
</beans>
需要进行增强的类的方法
public class ProductDaoImpl implements ProductDao{
@Override
public void save() {
System.out.println(“保存商品”);
}
@Override
public void update() {
System.out.println("修改商品");
}
@Override
public void find() {
System.out.println("查找商品");
}
@Override
public String delete() {
System.out.println("删除商品");
return "赵红";
}
}
运行结果
org.springframework.context.support.GenericApplicationContext@36d4b5c: startup date [Tue Dec 25 19:28:59 CST 2018]; root of context hierarchy
权限校验----execution(void com.heima.AopAspectJ.ProductDao.save())
保存商品
删除商品
日志记录------赵红
查找商品
最终通知
环绕前通知----execution(void com.heima.AopAspectJ.ProductDao.update())
修改商品
环绕后通知----execution(void com.heima.AopAspectJ.ProductDao.update())
每一个方法执行前都会进行权限校验,日志记录等,但是没有改变任何代码,如果不需要校验,或者日志,只需删除配置文件中的配置,不会改变源代码,非常符合面向对象的设计原则!!!
AOP的入门开发
- 引入jar包
aspectJ的包,spring的基础包,Spring和aspctJ的整合包,单元测试包(可不用JUnit4) - 填写目标并配置
- 编写切面并配置
- 进行AOP配置
打字好累,算了先写这么多。。。