নির্দিষ্ট টীকা সহ শ্রেণীর সমস্ত পদ্ধতির জন্য @ স্পেক্টজে পয়েন্টকুট


127

আমি নির্দিষ্ট টীকা সহ সমস্ত শ্রেণীর সমস্ত পাবলিক পদ্ধতিগুলি পর্যবেক্ষণ করতে চাই (@ মনিটর বলুন) (দ্রষ্টব্য: টীকাগুলি শ্রেণির স্তরে রয়েছে)। এর জন্য সম্ভাব্য পয়েন্টকুট কী হতে পারে? দ্রষ্টব্য: আমি @ স্পেক্টজে স্টাইলের স্প্রিং এওপি ব্যবহার করছি।


নীচে এক প্রসারিত কাজ করে। @ পয়েন্টকুট ("এক্সিকিউশন (* (@ org.rejeev.Monitor *)। * (..))") তবে এখন পরামর্শটি দু'বার কার্যকর করা হচ্ছে। কোন সুত্র?
রেজিভ দিবাকরণ

আর একটি বিষয় হ'ল @ মনিটর টীকাটি একটি ইন্টারফেসে রয়েছে এবং সেখানে একটি শ্রেণি প্রয়োগ করে। কোনও ইন্টারফেস এবং শ্রেণীর উপস্থিতি কি এই জাতীয় পরামর্শের দ্বিগুণ প্রয়োগের কারণ হতে পারে?
রেজিভ দিবাকরণ

6
আপনার নীচের দুর্দান্ত উত্তরটি গ্রহণ করা উচিত। এটি তাকে খ্যাতি দেয়। এসওতে এখানে মূল্যবান কয়েকজন লোক রয়েছেন যারা এসপেক্টজে প্রশ্নের উত্তর দিতে পারেন।
বোকা

উত্তর:


162

আপনি একটি পদ্ধতি পয়েন্টকট সঙ্গে একটি টাইপ পয়েন্টকুট একত্রিত করা উচিত।

এই পয়েন্টকাটগুলি @ মনিটরের টিকা দিয়ে চিহ্নিত শ্রেণীর ভিতরে সমস্ত পাবলিক পদ্ধতিগুলি সন্ধান করার জন্য কাজ করবে:

@Pointcut("within(@org.rejeev.Monitor *)")
public void beanAnnotatedWithMonitor() {}

@Pointcut("execution(public * *(..))")
public void publicMethod() {}

@Pointcut("publicMethod() && beanAnnotatedWithMonitor()")
public void publicMethodInsideAClassMarkedWithAtMonitor() {}

প্রথম দুটিকে সংযুক্ত করে শেষ পয়েন্টকুটটি পরামর্শ দিন এবং আপনি শেষ করেছেন!

আপনি যদি আগ্রহী হন তবে আমি এখানে @AspectJ শৈলীর সাথে একটি প্রাসঙ্গিক উদাহরণ ডকুমেন্ট সহ একটি প্রতারণামূলক শীট লিখেছি ।


ধন্যবাদ। আপনার ঠকানো পত্রকে টীকাগুলির পয়েন্টকাটগুলির আলোচনা বিশেষভাবে কার্যকর।
গ্রেগএনজেডজ

1
আমি কীভাবে ক্লাসের রেফারেন্স পেতে পারি যেভাবে আমি সাধারন পয়েন্টকুট পরামর্শগুলি দিয়ে যাই তা হল @ পূর্বে ("অনবজেক্ট অ্যাকশন () এবং & এটি (আপত্তি)")
প্রিয়দর্শী কুণাল

চিট শীটটি খুব সহায়ক ছিল, যদিও এটি 5 বছর হয়ে গেছে :)
ইয়াদু কৃষ্ণন

এখানে কেবল একটি প্রশ্ন, দুটি পদক্ষেপগুলি যদি হায়ারার্কিতে থাকে এবং উভয়ই পয়েন্টকটের আওতায় পড়ে এবং একই শ্রেণীর অন্তর্গত হয়, তবে এটি উভয়ের উপর কার্যকর হবে? যদি হ্যাঁ, তবে স্ট্যাকওভারফ্লো.com / প্রশ্নগুলি / 375৫৮৩৩৩৯ / / দেখুন , কারণ এটি আমার ক্ষেত্রে ঘটছে না।
এইচভিটি 7

আমি মনে করি ফাঁসি জনসাধারণ অপ্রয়োজনীয় কারণ আপনার ব্যক্তিগত পদ্ধতিতে পয়েন্টকাট থাকতে পারে না
amstegraf

58

প্রশ্নের মধ্যে বর্ণিত হিসাবে টীকাগুলি ব্যবহার করে।

টীকা: @Monitor

বর্গ উপর টীকা, app/PagesController.java:

package app;
@Controller
@Monitor
public class PagesController {
    @RequestMapping(value = "/", method = RequestMethod.GET)
    public @ResponseBody String home() {
        return "w00t!";
    }
}

পদ্ধতির উপর টীকা, app/PagesController.java:

package app;
@Controller
public class PagesController {
    @Monitor
    @RequestMapping(value = "/", method = RequestMethod.GET)
    public @ResponseBody String home() {
        return "w00t!";
    }
}

কাস্টম টীকা, app/Monitor.java:

package app;
@Component
@Target(value = {ElementType.METHOD, ElementType.TYPE})
@Retention(value = RetentionPolicy.RUNTIME)
public @interface Monitor {
}

টীকাগুলির জন্য দিক app/MonitorAspect.java,:

package app;
@Component
@Aspect
public class MonitorAspect {
    @Before(value = "@within(app.Monitor) || @annotation(app.Monitor)")
    public void before(JoinPoint joinPoint) throws Throwable {
        LogFactory.getLog(MonitorAspect.class).info("monitor.before, class: " + joinPoint.getSignature().getDeclaringType().getSimpleName() + ", method: " + joinPoint.getSignature().getName());
    }

    @After(value = "@within(app.Monitor) || @annotation(app.Monitor)")
    public void after(JoinPoint joinPoint) throws Throwable {
        LogFactory.getLog(MonitorAspect.class).info("monitor.after, class: " + joinPoint.getSignature().getDeclaringType().getSimpleName() + ", method: " + joinPoint.getSignature().getName());
    }
}

AspectJ সক্ষম করুন servlet-context.xml:

<aop:aspectj-autoproxy />

AspectJ গ্রন্থাগারগুলি অন্তর্ভুক্ত করুন pom.xml:

<artifactId>spring-aop</artifactId>
<artifactId>aspectjrt</artifactId>
<artifactId>aspectjweaver</artifactId>
<artifactId>cglib</artifactId>

1
চমৎকার উদাহরণ। একটি প্রশ্ন: টীকাকে কেন Monitorএকটি বসন্ত হতে হবে Component?
এমডব্লিউএস

1
Componentটীকা জিনিস Weaver AspectJ মধ্যে বর্গ অন্তর্ভুক্ত আবেদন করতে স্প্রিং ধারক বলতে ব্যবহৃত হয়। ডিফল্টরূপে, স্প্রিং শুধুমাত্র এ দেখায় Controller, Serviceএবং অন্যান্য নির্দিষ্ট টীকা, কিন্তু না Aspect
অ্যালেক্স

1
ঠিক আছে ধন্যবাদ. কিন্তু আমি সম্পর্কে কথা ছিল @Componentউপর টীকা @interfaceনা Aspect। কেন এটি প্রয়োজন?
এমডব্লিউএস

2
@Componentটীকা এটা তোলে তাই স্প্রিং AspectJ আইওসি / ডিআই দৃষ্টিভঙ্গি ওরিয়েন্টেড সিস্টেমের সাথে এটা কম্পাইল করতে হবে। কীভাবে এটি আলাদাভাবে বলতে হয় তা আমি জানি না। docs.spring.io/spring/docs/3.2.x/spring-framework-references/…
অ্যালেক্স

এটি কি টীকাযুক্ত শ্রেণিতে কেবল "পাবলিক" পদ্ধতিগুলি করে বা এটি সমস্ত পদ্ধতি (অ্যাক্সেস স্তর যাই হোক না কেন) করে?
লি মায়াদোর

14

এরকম কিছু:

@Before("execution(* com.yourpackage..*.*(..))")
public void monitor(JoinPoint jp) {
    if (jp.getTarget().getClass().isAnnotationPresent(Monitor.class)) {
       // perform the monitoring actions
    }
}

দ্রষ্টব্য যে এই শ্রেণীর আগে আপনার অবশ্যই একই শ্রেণীর জন্য অন্য কোনও পরামর্শ নেওয়ার দরকার নেই , কারণ প্রকাশনার পরে টিকাগুলি নষ্ট হবে।



4

এটির মতো আপনার দিকটি চিহ্নিত করার জন্য এটি যথেষ্ট হবে:

@After("@annotation(com.marcot.CommitTransaction)")
    public void after() {

কটাক্ষপাত আছে এই এই ধাপে নির্দেশিকা দ্বারা একটি ধাপ জন্য।


3

আপনি পয়েন্টকুট হিসাবেও সংজ্ঞায়িত করতে পারেন

public pointcut publicMethodInsideAClassMarkedWithAtMonitor() : execution(public * (@Monitor *).*(..));

খুব সহজ execution(public * @Monitor *.*(..))কাজ, খুব।
xmedeko

3

সবচেয়ে সহজ উপায় বলে মনে হচ্ছে:

@Around("execution(@MyHandling * com.exemple.YourService.*(..))")
public Object aroundServiceMethodAdvice(final ProceedingJoinPoint pjp)
   throws Throwable {
   // perform actions before

   return pjp.proceed();

   // perform actions after
}

এটি 'ইয়োর সার্ভিস' শ্রেণিতে '@ মাইহ্যান্ডলিং' দিয়ে বিশেষভাবে বর্ণিত সমস্ত পদ্ধতির কার্যকরকরণ বাধা দেবে। ব্যতিক্রম ছাড়াই সমস্ত পদ্ধতিকে বাধা দিতে, সরাসরি টীকাটি সরাসরি ক্লাসে রেখে দিন।

এখানে ব্যক্তিগত / জনসাধারণের ক্ষেত্রের বিষয়টি বিবেচনা করে না, তবে মনে রাখবেন যে বসন্ত-আওপ একই পদ্ধতিতে (সাধারণত ব্যক্তিগতভাবে) পদ্ধতি কলগুলির জন্য দিকটি ব্যবহার করতে পারে না, কারণ এটি এক্ষেত্রে প্রক্সি শ্রেণি ব্যবহার করে না।

আমরা এখানে @ চারপাশের পরামর্শ ব্যবহার করি তবে এটি মূলত @ পূর্ব, @ পরবর্তী বা কোনও পরামর্শের সাথে একই বাক্য গঠন।

যাইহোক, @ আমার হ্যান্ডলিং টীকাটি অবশ্যই এটির মতো কনফিগার করা উচিত:

@Retention(RetentionPolicy.RUNTIME)
@Target( { ElementType.METHOD, ElementType.TYPE })
public @interface MyHandling {

}

এটি মূল বক্তব্যটির উত্তর দিচ্ছে না, এলিমেন্টটাইপ.
অ্যালেক্স

হ্যাঁ, এলিমেন্টটাইপ.ওয়াইওয়াইপি সরাসরি ক্লাসগুলিতে টীকা লেখার অনুমতি দেবে, যা আমার ধারণা, এই শ্রেণীর যে কোনও পদ্ধতি পরিচালনা করতে হবে handle আমি কি সত্য? এটা কি সত্যিই কাজ করছে?
ডোনাটেলো

// perform actions afterআমরা আগে লাইনে মান ফিরে করছি যেহেতু কখনোই বলা হবে।
জোস্ফপকনলি

1

আপনি স্প্রিংয়ের পারফরম্যান্সমনিটরিং ইন্টারসেপ্টার ব্যবহার করতে পারেন এবং প্রোগ্রামালিভাবে একটি বিনপোস্টপ্রসেসর ব্যবহার করে পরামর্শটি নিবন্ধভুক্ত করতে পারেন।

@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface Monitorable
{

}


public class PerformanceMonitorBeanPostProcessor extends ProxyConfig implements BeanPostProcessor, BeanClassLoaderAware, Ordered,
    InitializingBean
{

  private Class<? extends Annotation> annotationType = Monitorable.class;

  private ClassLoader beanClassLoader = ClassUtils.getDefaultClassLoader();

  private Advisor advisor;

  public void setBeanClassLoader(ClassLoader classLoader)
  {
    this.beanClassLoader = classLoader;
  }

  public int getOrder()
  {
    return LOWEST_PRECEDENCE;
  }

  public void afterPropertiesSet()
  {
    Pointcut pointcut = new AnnotationMatchingPointcut(this.annotationType, true);
    Advice advice = getInterceptor();
    this.advisor = new DefaultPointcutAdvisor(pointcut, advice);
  }

  private Advice getInterceptor()
  {
    return new PerformanceMonitoringInterceptor();
  }

  public Object postProcessBeforeInitialization(Object bean, String beanName)
  {
    return bean;
  }

  public Object postProcessAfterInitialization(Object bean, String beanName)
  {
    if(bean instanceof AopInfrastructureBean)
    {
      return bean;
    }
    Class<?> targetClass = AopUtils.getTargetClass(bean);
    if(AopUtils.canApply(this.advisor, targetClass))
    {
      if(bean instanceof Advised)
      {
        ((Advised)bean).addAdvisor(this.advisor);
        return bean;
      }
      else
      {
        ProxyFactory proxyFactory = new ProxyFactory(bean);
        proxyFactory.copyFrom(this);
        proxyFactory.addAdvisor(this.advisor);
        return proxyFactory.getProxy(this.beanClassLoader);
      }
    }
    else
    {
      return bean;
    }
  }
}

1

বসন্তের থেকে AnnotationTransactionAspect:

/**
 * Matches the execution of any public method in a type with the Transactional
 * annotation, or any subtype of a type with the Transactional annotation.
 */
private pointcut executionOfAnyPublicMethodInAtTransactionalType() :
    execution(public * ((@Transactional *)+).*(..)) && within(@Transactional *);
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.