Spring

依赖注入与自动装配

基础装配

在这里插入图片描述

高级装配

在这里插入图片描述

从Profile注解的实现看Conditional注解和Condition接口

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional({ProfileCondition.class})
public @interface Profile {
    String[] value();
}
class ProfileCondition implements Condition {
    ProfileCondition() {
    }

    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        //从Profile类中获取所有的注解属性
        MultiValueMap<String, Object> attrs = metadata.getAllAnnotationAttributes(Profile.class.getName());
        if (attrs != null) {
            //从注解属性中得到value值,该值对应@Profile(配置名)中传入的配置名
            Iterator var4 = ((List)attrs.get("value")).iterator();
            Object value;
            //遍历配置名,判断在上下文环境中是否时激活profile,是则返回true
            do {
                if (!var4.hasNext()) {
                    return false;
                }
                value = var4.next();
            } while(!context.getEnvironment().acceptsProfiles(Profiles.of((String[])((String[])value))));

            return true;
        } else {
            return true; //默认返回true,视为无注解的加载
        }
    }
}

再来理解下Scope注解中proxyMode指定的动态代理:
在这里插入图片描述

面向切面AOP

依赖注入将组件及其协作组件解耦;AOP将应用组件与跨多个组件的任务进行解耦。
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在Performance接口的perform方法被调用前会执行切面Audience的silenceCellPhones逻辑;当perform方法执行完成会执行切面逻辑applause,否则抛出异常执行切面逻辑demandRefund。

注解完成切面

① 核心流程——以舞台演出为例,interface Performance定义演出接口;PerformanInstance类提供具体实现,并将其注解为组件,以自动注入

public interface Performance {
    void perform();
}

@Component
public class PerformInstance implements Performance {
    @Override
    public void perform() {
        System.out.println("唱一曲《向天再借五百年》!");
    }
}

② 织入切面Audience,增强功能。实现演出前后的观众动作。

@Aspect
@Component
public class Audience {
    @Pointcut("execution(** aspect.Performance.perform(..))")
    public void performance() {}
    //定义切点,用于可重用的切点,performance方法只是一个标识,供@Pointcut注解依附

    @Before("performance()") //等价于demandRefund的切点表达式用法
    public void silenceCellPhones() {
        System.out.println("Silencing cell phones 11111111");
    }
    @AfterReturning("performance()")
    public void applause() {
        System.out.println("Clap Clap Clap 22222222");
    }
    @AfterThrowing("execution(** aspect.Performance.perform(..))")
    public void demandRefund() {
        System.out.println("Demanding a refund.");
    }
    @Around("performance()")
    public void watchPerformance(ProceedingJoinPoint joinPoint) {
        try{
            System.out.println("Silencing cell phones  33333333");
            joinPoint.proceed(); //目标方法被调用,此处对应被增强的切点,即performance定义
            System.out.println("Clap Clap Clap 44444444");
        } catch (Throwable throwable) {
            demandRefund();
        }
    }
}

③ 引入切面,增加新功能。Encorable和DefaultEncoreable分别定义新接口并提供默认实现;EncoreableIntroducer注解为切面以及组件,声明为aspect.Performance子类的增强接口,默认实现为DefaultEncoreable

public interface Encorable {
    void dance();
}
public class DefaultEncoreable implements Encorable {
    @Override
    public void dance() {
        System.out.println("再跳一支舞。");
    }
}
@Aspect
@Component
public class EncoreableIntroducer {
    @DeclareParents(value = "aspect.Performance+", defaultImpl = DefaultEncoreable.class)
    public static Encorable encorable;
}

④ JavaConfig配置类,注解EnableAspectJAutoProxy 启用Aspect J自动代理功能,启用组件扫描

@Configuration
@EnableAspectJAutoProxy //启用AspectJ自动代理功能
@ComponentScan
public class AutoConfig {
}

⑤测试类及其结果

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {AutoConfig.class})
public class AspectTest {
    @Autowired
    private Audience audience;
    @Autowired
    private Performance performance;

    @Test
    public void testAspect() {
        performance.perform();
        if (performance instanceof Encorable) {
            ((Encorable) performance).dance();
        }
    }
}
结果为:
Silencing cell phones  33333333
Silencing cell phones 11111111
唱一曲《向天再借五百年》!
Clap Clap Clap 44444444
Clap Clap Clap 22222222
再跳一支舞。

XML完成切面

主要用于通知类无法获知源码或者无法更改的情况下,将POJO的通知类声明为bean,声明为切面,进行AOP操作。思路与基于Config配置类完全一致。不再举例。

总结

AOP是OOP的强大补充。通过Aspect J,将分散在应用各处的行为放入可重用的模块中。显式地声明在何处如何应用这些行为。减少了代码冗余,提高核心功能对自身的关注度。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值