2017-07-07 25 views
0

spring-boot aopデモが実装されていて、うまく動作しますが、プロジェクトを開始するときにリソースをロードするために使用する場合は、何とか動作しません。プロジェクト開始時にSpring aopが実行されない

量Aop:

package com.neo.mysql; 

import org.aspectj.lang.JoinPoint; 
import org.aspectj.lang.annotation.After; 
import org.aspectj.lang.annotation.Aspect; 
import org.aspectj.lang.annotation.Before; 
import org.aspectj.lang.reflect.MethodSignature; 
import org.springframework.stereotype.Component; 

import java.lang.reflect.Method; 

/** 
* Created by li_weia on 2017/7/6. 
*/ 
@Aspect 
@Component 
public class DynamicDataSourceAspect { 

    @Before("@annotation(VendorSource)") 
    public void beforeSwitchDS(JoinPoint point){ 

     //获得当前访问的class 
     Class<?> className = point.getTarget().getClass(); 

     //获得访问的方法名 
     String methodName = point.getSignature().getName(); 
     //得到方法的参数的类型 
     Class[] argClass = ((MethodSignature)point.getSignature()).getParameterTypes(); 
     String dataSource = DataSourceContextHolder.DEFAULT_DS; 
     try { 
      // 得到访问的方法对象 
      Method method = className.getMethod(methodName, argClass); 

      // 判断是否存在@DS注解 
      if (method.isAnnotationPresent(VendorSource.class)) { 
       VendorSource annotation = method.getAnnotation(VendorSource.class); 
       // 取出注解中的数据源名 
       dataSource = annotation.value(); 
      } 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 

     // 切换数据源 
     DataSourceContextHolder.setDB(dataSource); 

    } 


    @After("@annotation(VendorSource)") 
    public void afterSwitchDS(JoinPoint point){ 

     DataSourceContextHolder.clearDB(); 

    } 
} 

VendorSource注釈:それは、私が正常にアノテーションでデータソースを変更することができ、ここでうまく動作します

package com.neo.mysql; 

import java.lang.annotation.ElementType; 
import java.lang.annotation.Retention; 
import java.lang.annotation.RetentionPolicy; 
import java.lang.annotation.Target; 

/** 
* Created by li_weia on 2017/7/6. 
*/ 
@Target({ ElementType.METHOD, ElementType.TYPE }) 
@Retention(RetentionPolicy.RUNTIME) 
public @interface VendorSource { 
    String value() default "vendor-master"; 
} 

package com.neo.web; 

import com.neo.entity.SiteEntity; 
import com.neo.mapper.ClassMappingDao; 
import com.neo.mysql.VendorSource; 
import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.web.bind.annotation.RequestMapping; 
import org.springframework.web.bind.annotation.RestController; 

import java.util.List; 

@RestController 
public class UserController { 

    private final ClassMappingDao siteMapper; 

    @Autowired(required = false) 
    public UserController(ClassMappingDao siteMapper) { 
     this.siteMapper = siteMapper; 
    } 

    @RequestMapping("/getSites") 
    @VendorSource("vendor-read") 
    public List<SiteEntity> getUsers() { 
     return siteMapper.getAllSite(); 
    } 
} 

が、それはここで働いていない、AOPメソッドがすべてで呼び出されていません。

package com.neo.component; 

import com.neo.entity.SiteEntity; 
import com.neo.mapper.ClassMappingDao; 
import com.neo.mysql.VendorSource; 
import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.stereotype.Component; 

import java.util.List; 

/** 
* Created by li_weia on 2017/7/7. 
*/ 
@Component 
public class TestComponent{ 
    private final ClassMappingDao userMapper; 

    @Autowired(required = false) 
    public TestComponent(ClassMappingDao userMapper) { 
     this.userMapper = userMapper; 
     init(); 
    } 

    @VendorSource("vendor-read") 
    public void init() { 
     List<SiteEntity> sites = userMapper.getAllSite(); 
     for(SiteEntity site: sites){ 
      System.out.println(site.getSite()); 
     } 
    } 
} 
+0

TestComponentを正常に初期化することができます。デフォルトのデータソースが使用されていて、アノテーションがまったく機能しないようです。 – Levy

+0

AOPをどのように有効にしましたか? –

+0

のアスペクトとコンポーネント注釈付きでは、スプリングブートにより自動的に有効になります – Levy

答えて

0

あなたがそうのように、完全に注釈を修飾する必要があります。また

@Before("execution(public * *(..)) && @annotation(com.neo.mysql.VendorSource)") 
private void whatever() {} 

、上記の私のコメントで述べたように、クラスパスにはspring-boot-starter-aopが必要です。たぶんあなたはすでにしているかもしれませんが、あなたが言わなかったので、それは言及する価値があります。

編集

私は注意を払っていなかった、前に本当の問題に気付きませんでした。

  1. 別のクラスからの呼び出しを行う場合にのみ、Spring AOPがトリガーされます。これは、Springが呼び出しをインターセプトしてポイントカットを実行できる必要があるためです。コンストラクタからメソッドを呼び出すことは何もしません。

  2. ハックリの回避策を実行できます。あなたのクラス(コンストラクタではありません)に@PostConstruct void postConstruct() {}メソッドを作成し、ApplicationContextをオートワイヤし、postConstructメソッドでMyClassWithInitMethod myClass = context.getBean(MyClassWithInitMethod.class)を実行します。その後myClass上のメソッドを呼び出し、そしてAOPがでキックします。

を率直に言って、私は以前に、あなたのポイントカットで何をしているかチェックしていなかった、そしてそれはひどいアイデアです。複数のスレッドが実行されると、静的コンテキストが上書きされ、競合条件が作成され、次に別の質問が作成されます。 しないでください!代わりにファクトリパターンを使用し、DataSourceFactoryを注釈を持つクラスに挿入します。

+0

あなたは言ったように、コントローラがうまく動作している間はinitメソッドが期待通りに動作しません。 – Levy

+0

'init'メソッドは別のパッケージにあるクラスにあります。あなたはそれをスキャンしていますか? –

+0

はい、スプリングブートは私のために行います。サイトが 'System.out.println(site.getSite()) 'によって印刷されているのを見ることができますが、他のデータベース – Levy

関連する問題