簡體   English   中英

Spring Bean 配置

[英]Spring Bean Config

我正在學習帶有注釋和 xml 配置的 bean AOP,但 Spring 不會創建 bean。

界面

package com.spring.studying.SpringAop.FrameworkService.AspectJAnnotation;

public interface Artist {
    void perform();
}

吉他 Class

package com.spring.studying.SpringAop.FrameworkService.AspectJAnnotation;


import org.springframework.stereotype.Component;

@Component("grammyGuitarist")
public class GrammyGuitarist implements Artist{

    @Override
    public void perform() {
        System.out.println("Start to play guitar");
    }

    public void playGuitar(String brand)
    {
        System.out.println("Get Guitar "+brand);
    }
    public void rest()
    {
        System.out.println("zzZZ!!!!");
    }
}

紀錄片導演

package com.spring.studying.SpringAop.FrameworkService.AspectJAnnotation;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component(value="documentaries")
public class Documentarist {
    private GrammyGuitarist guitarist;
    public void executed()
    {
        guitarist.playGuitar("LakeWood");
        guitarist.perform();
        guitarist.rest();
    }

    @Autowired
    public void setGuitarist(GrammyGuitarist guitarist) {
        this.guitarist = guitarist;
    }
}

建議 Class

package com.spring.studying.SpringAop.FrameworkService.AspectJAnnotation;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

@Component("annotatedAdvice")
@Aspect
public class AnnotatedAdvice {
    @Pointcut("execution(* rest*(..)) && args(brand)")
    public void restExecution(String brand)
    {

    }

    @Pointcut("bean(grammyGuitarist)")
    public void isGrammyGuitarist()
    {

    }

    @Before("restExecution(brand) && isGrammyGuitarist")
    public void simpleBeforeAdvice(JoinPoint joinPoint , String brand)
    {
        System.out.println("Before Advice processing");
        System.out.println("Playing guitar :" + brand);
        System.out.println("Executing :"+ joinPoint.getSignature().getDeclaringTypeName() +" "+joinPoint.getSignature().getName());

    }

}

演示 Class

package com.spring.studying.SpringAop.FrameworkService.AspectJAnnotation;

import org.springframework.context.support.GenericXmlApplicationContext;

import java.util.Arrays;


public class AspectJAnnotationDemo {
    public static void main(String[] args) {
        GenericXmlApplicationContext ctx = new GenericXmlApplicationContext();
        ctx.load("aop-aspectj-annotation-style.xml");
        ctx.refresh();
        Arrays.stream(ctx.getBeanDefinitionNames()).forEach(System.out::println);
        Documentarist documentarist = ctx.getBean("documentaries",Documentarist.class);
        documentarist.executed();
    }
}

我的 Xml 配置文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context.xsd
    http://www.springframework.org/schema/aop
    http://www.springframework.org/schema/aop/spring-aop.xsd
    ">
    <context:annotation-config/>
    <context:component-scan base-package="com.spring.studying.SpringAop"/>


    <aop:aspectj-autoproxy/>
</beans>

我的 bean 都不是僅從 spring 中創建的 6 個默認 bean。

我嘗試用標簽創建 bean,它工作正常。 只是不知道為什么我的代碼不適用於注釋。

restExecution @Pointcut是錯誤的,因為restGrammyGuitarist方法不采用任何 arguments。 playGuitar方法接受brand參數,所以你需要稍微改變你的切入點:

@Component("annotatedAdvice")
@Aspect
public class AnnotatedAdvice {
    @Pointcut("execution(* play*(..)) && args(brand)")
    public void playExecution(String brand) {

    }

    @Pointcut("bean(grammyGuitarist)")
    public void isGrammyGuitarist() {

    }

    @Before("playExecution(brand) && isGrammyGuitarist()")
    public void simpleBeforeAdvice(JoinPoint joinPoint, String brand) {
        System.out.println("Before Advice processing");
        System.out.println("Playing guitar :" + brand);
        System.out.println("Executing :" + joinPoint.getSignature().getDeclaringTypeName() + " " + joinPoint.getSignature().getName());

    }
}

當你這樣做時,方面確實會被創建,但你會開始得到異常:

Bean named 'grammyGuitarist' is expected to be of type 'com.example.demo.aspect.GrammyGuitarist' but was actually of type 'jdk.proxy2.$Proxy14'

這是因為GrammyGuitarist實現了一個接口, 在這種情況下Spring AOP使用 JDK 動態代理

最簡單的解決方案是強制使用 CGLIB 代理。 為此,您需要在方面上方添加注釋:

@EnableAspectJAutoProxy(proxyTargetClass = true)

之后,程序將給出預期的結果:

annotatedAdvice
documentaries
grammyGuitarist
org.springframework.aop.config.internalAutoProxyCreator
Before Advice processing
Playing guitar :LakeWood
Executing :com.example.demo.aspect.GrammyGuitarist playGuitar
Get Guitar LakeWood
Start to play guitar
zzZZ!!!!

在 Spring Boot 中,默認啟用 CGLIB 強制。 檢查這個問題以獲得更好的理解

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM