Spring 学习很瘦身2

来源:互联网 发布:新手学美工 编辑:程序博客网 时间:2024/06/02 03:29

  • AOP 面向切面编程
    • 1 实现方式
    • 2 Spring中的作用
    • 3 Spring中的实现
  • 二AOP 概念介绍
    • 1 aspect 切面
    • 2 pointcut 切入点
      • 21 切入方法
      • 22 切入类型
      • 23 切入示例
      • 24 切入组合
      • 25 切入规范
    • 3 Advice 通知
      • 31 使用实例
      • 32 使用扩展
    • 4 Introduction 引入
    • 5 Advisors
    • 6 AOP Proxy 代理
      • 61 Target Object 目标对象
      • 62 Proxy 的定义
  • AOP API 的使用
  • 注解 AspectJ
  • 切面实例化模型

AOP 面向切面编程

AOP(aspect-oriented-programming)确保 POJO 的简单性以及核心业务的内聚性,借助 AOP 可以将安全、事务和日志关注点与核心业务逻辑相分离。

1. 1 实现方式

  • 预编译
    • AspectJ
  • 运行期动态代理(JDK 动态代理、CGLib 动态代理)
    • SpringAOP、JbossAOP

1.2 Spring中的作用

  • 提供声明式的企业服务,特别是 EJB 的替代服务声明
  • 允许自定义方面,互补 OOP(面向对象) 与 AOP(面向切面)的使用

1.3 Spring中的实现

  • 接口/接口集默认 JavaSE 动态代理作为 AOP 的代理标准
  • 无接口可使用 GCGLIB 的代理实现

二、AOP 概念介绍

2.1 aspect 切面

<?xml version="1.0" encoding="UTF-8"?><beans ...>    <!-- 切面类 -->    <bean id="AspectBean_id" class=[AspectBeanPath]/>       <!-- 业务类 -->    <bean id="BizBean_id" class=[BizBeanPath]/>    <aop:config>        <aop:aspect id="AspectBeanAOP_id" ref="AspectBean_id"/>    </aop:config><beans>

2.2 pointcut 切入点

2.2.1 切入方法

function impact execution 匹配方法执行的连接点 within/@within 限定匹配指定类型的连接点 this 匹配特定连接点的 bean,引用柿子顶类型实例的限制 target/@target 限定匹配当特定连接点的代理对象,对象是指定类型的实例 args/@args 限定匹配特定连接点实际传入参数的类型实例 @annotation 限定匹配指定连接点的主体

2.2.2 切入类型

example pointcut excution(public * *(..)) 所有 public 执行方法 excution(* set*(..)) 所有 set 开始的方法 excution(* com.example.bean.AClazz.*(..)) AClazz 类中所有方法 excution(* com.example.bean..(..)) com.example.bean 包下所有方法 excution(* com.example.bean…(..)) com.example.bean 包即包下所有方法

2.2.3 切入示例

<?xml version="1.0" encoding="UTF-8"?><beans ...>    <!-- 切面类 -->    <bean id="AspectBean_id" class=[AspectBeanPath]/>       <!-- 业务类 -->    <bean id="BizBean_id" class=[BizBeanPath]/>    <aop:config>        <aop:aspect id="AspectBeanAOP_id" ref="AspectBean_id">            <aop:pointcut expression="excution(public * *(..))" id=[POINTCUT_ID]/>        </aop:aspect>     </aop:config><beans>

2.2.4 切入组合

表达式可通过 &&、|| 或者 ! 进行组合,亦可通过名字引用切入点表达式,如下:

@Pointcut("excution(...)")private void aFunction(){}@Pointcut("excution(...)")private void bFunction(){}@Pointcut("aFunction() && bFunction()")private void cFunction(){}

2.2.5 切入规范

  • 选择特定类型的连接点,如:execution,get,set,call,handler
  • 确定连接点范围,如:within,withincode
  • 匹配上下文信息,入:this,target,@annotation

2.3 Advice 通知

2.3.1 使用实例

<aop:aspect id="AspectBeanAOP_id" ref="AspectBean_id">    <aop:pointcut expression="excution(public * *(..))" id=[POINTCUT_ID]/>    <!-- 执行时前置通知 -->    <aop:before method = [AspectBean_DO_FUNCTION] pointcut-ref=[POINTCUT_ID]/>    <!-- 返回时,受已成影响 -->    <aop:after-returning method = [AspectBean_DO_FUNCTION] pointcut-ref=[POINTCUT_ID]/>    <!-- 异常时 -->    <aop:after-throwing method = [AspectBean_DO_FUNCTION] pointcut-ref=[POINTCUT_ID]/>    <!-- 执行完后置通知,不受异常影响 -->    <aop:after method = [AspectBean_DO_FUNCTION] pointcut-ref=[POINTCUT_ID]/>    <!-- 同上不受异常干扰,多用于资源的释放 -->    <aop:finally method = [AspectBean_DO_FUNCTION] pointcut-ref=[POINTCUT_ID]/>    <!-- 环绕执行,即执行前于执行后。位于通知方法首个参数必需为 ProceedingJoinPoint 类型 -->    <aop:aspect method = [AspectBean_DO_FUNCTION] pointcut-ref=[POINTCUT_ID]/></aop:aspect> 

或通过代码实现:

@Component@Aspectpublic class MoocAspect {    @Before("execution(...)")    public void befor() {}    @After("execution(...)")    public void after() {        // after、finally 的实现    }    @AfterReturning(pointcut="execution(...)", returning="returnValue")    public void afterReturning(Object returnValue) {        // retrunValue 具体返回值,类型可依据实际情况确认        }    @AfterThrowing(pointcut="execution(...)", throwing="e")    public void afterThrowing(Exception e) {        // e 具体异常类型信息,异常可依据实际情况确认       }    @Around("execution(...)")    public Object around(ProceedingJoinPoint pjp) throws Throwable {        // 此处执行于方法前        Object obj = pjp.proceed();// 真正执行的行为,obj 可能为 null        // 此处执行于方法后        return obj;    }}

2.3.2 使用扩展

  • 参数
@Component@Aspectpublic class MoocAspect {    @Before("execution(...) && args(arg)")    public void beforeWithParam(String arg) {        // arg 获取传入参数值    }    @Before("execution(...) && @annotation(moocMethod)")    public void beforeWithAnnotaion(MoocMethod moocMethod) {        // moocMethod 获取传入注解内容    }    @Before("execution(...) && args(arg) && @annotation(moocMethod)",        argName="arg, moocMethod")    public void beforeWithArgNames(String arg, MoocMethod moocMethod) {        // 指定注解方法的参数名        // JoinPoint,ProceedingJoinPoint,JoinPoint.StraticPart 可忽略    }}
  • 泛型
public interface Sample<T>{    void sampleGenericMethod(T param);    void sampleGenericCollectionMethod(Coolection<T> param);}
@Component@Aspectpublic class MoocAspect {    @Before("execution(..Sample.sampleGenericMethod(*)) && args(arg)")    public void beforeWithParam(String arg) {        // arg 指定泛型类型为 String    }    @Before("execution(..Sample.sampleGenericCollectionMethod(*)) && args(arg)")    public void beforeWithParam(Collection<String> arg) {        // arg 指定泛型集合类型为 String    }}

2.4 Introduction 引入

允许一个切面声明一个实现指定接口的通知对象,并提供了一个接口实现类来代表这些对象。实现方式:

  • 在 < aop:aspect > 声明 < aop:declare-parents > 匹配新的 parent
<aop:config>    <aop:aspect id="" ref="">        <aop:declare-parents            <!-- 指定接口对象 -->            implement-interface=""            <!-- 接口实现,代表以上对象 -->            defalult-impl=""/>    </aop:aspect></aop:config>
  • 代码中使用 @DeclareParents 进行注解,且用来匹配拥有新的 parent
public interface Sample{    void sampleMethod();}
@Aspectpublic class IntroductionAspect {    @DeclareParents(value="execution(...)", defaultImpl=Sample.class)    public static Sample sample;    @Before("execution(...) && this(sample2)")    public void recordIntroduction(Sample sample2) {        sample2.sampleMethod();    }}

2.5 Advisors

  • 仅有一个 advice , 切面自身通过一个 bean 表示并实现相应的 advice 接口;

2.6 AOP Proxy 代理

2.6.1 Target Object 目标对象

  • 默认 CGLIB 代理
  • 实际通过 ProxyFatoryBean 对象的 getObject() 函数获取到代理对象
  • 配置文件当中通过 < proerty name=”target”> 声明代理对象
  • 继承接口 MethodInterceptor 可实现 *通配符设定

2.6.2 Proxy 的定义

<bean id="" class="org.springframework.aop.framework.ProxyFactoryBean">    <property name="target"><bean ...></property>    <property name="interceptorNames"><list><value>...</list></property></bean>  

可通过以下方式,简化以上定义:

<bean id="baseProxyBean" class="org.springframework.aop.framework.ProxyFactoryBean"             lazy-init="true" abstract="true"></bean><bean id="" parent="baseProxyBean">    <property name="target"><bean ...></property>    <property name="interceptorNames"><list><value>...</list></property></bean>  

通过以下方式,实现自动代理 auto-proxy

<bean id="" class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">    <property name="beanNames" value=[通配符定义]/>    <property name="interceptorNames"><list><value>...</list></property></bean>  

同样的,可以通过以下方式简化以上自动代理(暂为理解,后继完善)

<bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"/>

AOP API 的使用

api method impact BeforeAdvice void before(Method m, Object[] args, Object target) 连接点插入前执行 ThrowsAdvice void afterThrowing([Method, args, target], ThrowableSubclass) 连接点返回后执行 AfterReturningAdvice void afterReturning(Object returnValue, Method m, Object[] args, Object target) 后置通知必需实现 Interceptor Object invoke(MethodInvocation invocaton) 针对不同的 advice 启用相同的切入点 IntroductionInterceptor boolean implementsInterface(Class intf) IntroductionAdvisor void validateInterfaces() IntroductionInfo Class[] getInterfaces() Lockable void lock()
void unlock()
boolean locaked()
Object invoke(MethodInvocation invocation) 锁住
解锁
锁状态
根据锁状态的操作 DefaultIntroductionAdvisor LockMixinAdvisor() 持独立 LockMixin 实例的构造函数

注解 @AspectJ

注解类型 描述 @Commponent 声明可以被 bean 容器识别 @Aspect 切面 1.注解 bean 将被 Spring 自动识别并应用
2.可包括切入点 pointcut,通知 Advice 和引入 introduction 的声明
3.需配合 @Component 注释或 xml 配置 @Pointcut 切入点 方法返回类型必需是 void

切面实例化模型

在对象执行并创建切面实例后跟随对象的失效而失效(fk:有句麻卖批不知当讲不当讲,不管先记录下再说),以下为具体实现

@Aspect("perthis(execution(...))")public class MyAspect {}

Spring 学习很瘦身1
Spring 学习很瘦身2

原创粉丝点击