【Spring-Framework】Spring-framework文档阅读笔记——Core(下)

5 篇文章 0 订阅

5.1. AOP Concepts——AOP概念

  • Aspect: modularization of a concern that cuts across multiple classes. 翻译为切面:对于横跨多个类的关注点的模块化。举例来讲,开启事务这个操作要在数据库增删改之前执行,这个操作要插入在所有增删改操作之前,那么开启事务这个操作就是横跨了多个类的一个关注点,他就是一个切面。
  • Join point: A point during the execution of a program. 翻译为连接点:程序运行中的一个点。举例:一个方法就是一个连接点,spring中连接点指的就是方法。在AOP中,我们需要将切面放在某个方法之前或者之后等等,就是将切面与方法进行连接,使程序可以依次执行,而每个方法都可以进行连接操作,所以每个方法就都是一个连接点。
  • Advice: Action taken by an aspect at a particular join point. 翻译为通知: 切面在连接点执行的动作。比如之前提到开启事务这个操作,就是切面在连接点执行的动作,就是通知,指的是切面具体干的事儿是啥。
  • Pointcut: A predicate that matches join points. 翻译为切入点:匹配连接点断言。虽然每个连接点都可以连接切面,但实际场景中,我们仅仅需要对某些连接点插入切面,切入点的简单意思就是去匹配符合条件的、需要进行切面插入的连接点。
  • Introduction: Declaring additional methods or fields on behalf of a type. 翻译为引入:为类声明额外的方法和字段。这个功能可以帮助一个类成为某一个其实际上没有实现的接口的实现类。
  • Target object: An object being advised by one or more aspects. 翻译为目标对象:被切面通知的对象。例如DAO对象里的增删改方法需要被事务切面通知,这个DAO对象就是目标对象。
  • AOP proxy: An object created by the AOP framework in order to implement the aspect contracts. 翻译为AOP代理:AOP框架创建的用于实现切面的代理对象
  • Weaving: linking aspects with other application types or objects to create an advised object. 翻译为编织:将切面与目标类联系在一起从而创建目标对象。指的是这个动作。

5.4. @AspectJ support

5.4.2. Declaring an Aspect

With @AspectJ support enabled, any bean defined in your application context with a class that is an @AspectJ aspect (has the @Aspect annotation) is automatically detected by Spring and used to configure Spring AOP.

这也就是说,切面需要注册进容器里才能成功被使用

5.4.3. Declaring a Pointcut

注意,spring里切面本身不能再被其他切面切入,就是说其方法只能作为advice,不能作为pointcut,也就是说不能套娃。

5.5.4. Declaring Advice

  • Access to the Current JoinPoint
    由于ProceedingJoinPoint可以通过getArgs获取参数,因此可以对参数进行手动修改,例如
@Around(value = "getBlogPt()")
    public Object getBlogAround(ProceedingJoinPoint pjp) throws Throwable{
        System.out.println("before getBlog");
        Author author = (Author) pjp.getArgs()[0];
        author.setId(author.getId()+1);
        Object object=pjp.proceed();
        System.out.println("after getBlog 我来看看这个blog");
        System.out.println(object);
        return object;
    }
  • Passing Parameters to Advice
@Before("com.xyz.myapp.SystemArchitecture.dataAccessOperation() && args(account,..)")
public void validateAccount(Account account) {
    // ...
}

The args(account,…) part of the pointcut expression serves two purposes. First, it restricts matching to only those method executions where the method takes at least one parameter, and the argument passed to that parameter is an instance of Account. Second, it makes the actual Account object available to the advice through the account parameter.

  • Advice Order

Given two aspects, the aspect returning the lower value from Ordered.getValue() (or the annotation value) has the higher precedence.

5.4.5. Introductions

下面代码的意思就是:com.xzy.myapp.service包下面所有类的实现类,都又实现了一个UsageTracked接口,实现方法由DefaultUsageTracked.class决定

@DeclareParents(value="com.xzy.myapp.service.*+", defaultImpl=DefaultUsageTracked.class)
public static UsageTracked mixin;

这个功能只会影响容器创建的com.xzy.myapp.service.*类对象,可以成功类型转换;不会影响手动new出来的对象,类型转换会失败。

5.4.6. Aspect Instantiation Models

文档里说

@Aspect("perthis(com.xyz.myapp.SystemArchitecture.businessService())")

In the preceding example, the effect of the ‘perthis’ clause is that one aspect instance is created for each unique service object that executes a business service (each unique object bound to ‘this’ at join points matched by the pointcut expression).

但我发现, 如果切面的作用域是prototype,那就是每个目标类对象都有一个对应的切面对象啊。
不过我发现,如果某个切面带有下面的注解,那么这个切面类里的advice通知方法就只能对注解里写的这个PointCut生效了

@Aspect("perthis(execution(* service.BlogServiceImp.getBlog(..)))")

5.5. Schema-based AOP Support

Within your Spring configurations, all aspect and advisor elements must be placed within an <aop:config> element (you can have more than one <aop:config> element in an application context configuration). An <aop:config> element can contain pointcut, advisor, and aspect elements (note that these must be declared in that order).

5.5.2. Declaring a Pointcut

示例代码好像有错,下面代码不应该是this,而应该是args

<aop:config>
    <aop:aspect id="myAspect" ref="aBean">
        <aop:pointcut id="businessService"
            expression="execution(* com.xyz.myapp.service.*.*(..)) && this(service)"/>
        <aop:before pointcut-ref="businessService" method="monitor"/>
   </aop:aspect>
</aop:config>

5.5.6. Advisors

Advisor: An advisor is like a small self-contained aspect that has a single piece of advice.
可以翻译成通知者,文档给出的解释是,通知者是一个只有一个通知Advice自管理切面

  • 首先,Advisor是一个与切面,他又叫通知者,说明他和普通切面一样,包含着各种通知;
  • 其次,他的名字叫做通知者,而且文档中说了他是自管理的,说明这个切面不需要我们手动指定aop:before之类的通知配置,而可以根据情况或者配置自动执行相应的通知操作。

例如事务管理操作

    <!-- 配置事务管理器 -->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>

    <!-- 配置事务的通知-->
    <tx:advice id="txAdvice" transaction-manager="transactionManager">
        <!-- 配置事务的属性
                isolation:用于指定事务的隔离级别。默认值是DEFAULT,表示使用数据库的默认隔离级别。
                propagation:用于指定事务的传播行为。默认值是REQUIRED,表示一定会有事务,增删改的选择。查询方法可以选择SUPPORTS。
                read-only:用于指定事务是否只读。只有查询方法才能设置为true。默认值是false,表示读写。
                timeout:用于指定事务的超时时间,默认值是-1,表示永不超时。如果指定了数值,以秒为单位。
                rollback-for:用于指定一个异常,当产生该异常时,事务回滚,产生其他异常时,事务不回滚。没有默认值。表示任何异常都回滚。
                no-rollback-for:用于指定一个异常,当产生该异常时,事务不回滚,产生其他异常时事务回滚。没有默认值。表示任何异常都回滚。
        -->
        <tx:attributes>
            <tx:method name="*" propagation="REQUIRED" read-only="false"/>
            <tx:method name="find*" propagation="SUPPORTS" read-only="true"/>
        </tx:attributes>
    </tx:advice>

    <!-- 配置aop-->
    <aop:config>
        <!-- 配置切入点表达式-->
        <aop:pointcut id="pt1" expression="execution(* com.itheima.service.impl.*.*(..))"/>
        <!--建立切入点表达式和事务通知的对应关系 -->
        <aop:advisor advice-ref="txAdvice" pointcut-ref="pt1"/>
    </aop:config>

5.6. Choosing which AOP Declaration Style to Use

5.6.1. Spring AOP or Full AspectJ?

If you need to advise objects not managed by the Spring container (such as domain objects, typically), you need to use AspectJ.

Spring只能对ioc容器中的对象进行切面编程,假如我们对Author类的getName添加了before advice,第一个getName就能执行before advice,第二个就不行

        Author author = ac.getBean("author1", Author.class);
        author.getName();
        new Author().getName();

5.6.2. @AspectJ or XML for Spring AOP?

XML配置的缺点1:切面的声明和使用分在了两个地方
缺点2:没法合并多个定义好的切入点表达式

5.8. Proxying Mechanisms

5.8.1. Understanding AOP Proxies

在Spring AOP代理里面提到了self-invocation——自调用,比如说现在有一个类声明如下

public class SimplePojo implements Pojo {
    public void foo() {
        // this next method invocation is a direct call on the 'this' reference
        this.bar();
    }
    public void bar() {
        // some logic...
    }
}

然后我们对这个SimplePojo的全部方法进行代理

class MyAdvice implements MethodBeforeAdvice {
            @Override
            public void before(Method method, Object[] objects, Object o) throws Throwable {
                System.out.println("before");
            }
        }
ProxyFactory factory = new ProxyFactory(new SimplePojo());
factory.addInterface(Pojo.class);
factory.addAdvice(new MyAdvice());
Pojo pojo=(Pojo)factory.getProxy();
pojo.foo();

我们会发现,foo方法被代理了,但由于foo方法还调用了bar方法,foo方法里的bar方法并不是代理版本的;这个就是代理的自调用引出的问题。
文档里给出的解决方法是把容器维护的代理对象告诉给这个被代理对象。

5.9. Programmatic Creation of @AspectJ Proxies

这个就是编程实现AOP功能,挺简单的,关键的就是几个Advice接口

5.10. Using AspectJ with Spring Applications

我没用过AspectJ,所以这章看的云里雾里

5.10.1. Using AspectJ to Dependency Inject Domain Objects with Spring

Spring只能对容器创建的对象进行依赖注入,而通过使用@Configurable,可以对new出来的对象进行依赖注入。
专门写了一篇博客,文档中提到,为了这个功能起作用,the annotated types must be woven with the AspectJ weaver. You can either use a build-time Ant or Maven task to do this (see, for example, the AspectJ Development Environment Guide) or load-time weaving (see Load-time Weaving with AspectJ in the Spring Framework).
也就是说要么使用Maven进行编译,要么通过LTW进行实现

5.10.3. Configuring AspectJ Aspects by Using Spring IoC

下面是注册特定的切面类的方法,也就是说只注册了annoAspect这个切面,其余切面不起作用

    <bean id="annoAspect" class="myAspect.AnnoAspect"/>
    <aop:aspectj-autoproxy>
        <aop:include name="annoAspect"/>
    </aop:aspectj-autoproxy>

5.10.4. Load-time Weaving with AspectJ in the Spring Framework

XML配置不好使,但注解配置好使,代码

6. Spring AOP API

代码demo
就是使用spring对对象进行代理,里面涉及了advisor等应用

6.7. Manipulating Advised Objects

If you added an interceptor or other advice type, Spring wrapped this in an advisor with a pointcut that always returns true.

就是说所有的advice在实际应用的时候都会被包装成一个Advisor

6.8 using Auto-proxy facility

不需要对每个目标对象手动配置,而是对目标对象自动生成代理对象

BeanNameAutoProxy

根据名称对目标对象进行代理

DefaultAdvisorAutoProxy

自动搜索容器内的Advisor,然后根据这些AdvisorPointCut对容器内的对象进行代理

6.9 using TargetResource

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值