আমি নির্দিষ্ট টীকা সহ সমস্ত শ্রেণীর সমস্ত পাবলিক পদ্ধতিগুলি পর্যবেক্ষণ করতে চাই (@ মনিটর বলুন) (দ্রষ্টব্য: টীকাগুলি শ্রেণির স্তরে রয়েছে)। এর জন্য সম্ভাব্য পয়েন্টকুট কী হতে পারে? দ্রষ্টব্য: আমি @ স্পেক্টজে স্টাইলের স্প্রিং এওপি ব্যবহার করছি।
আমি নির্দিষ্ট টীকা সহ সমস্ত শ্রেণীর সমস্ত পাবলিক পদ্ধতিগুলি পর্যবেক্ষণ করতে চাই (@ মনিটর বলুন) (দ্রষ্টব্য: টীকাগুলি শ্রেণির স্তরে রয়েছে)। এর জন্য সম্ভাব্য পয়েন্টকুট কী হতে পারে? দ্রষ্টব্য: আমি @ স্পেক্টজে স্টাইলের স্প্রিং এওপি ব্যবহার করছি।
উত্তর:
আপনি একটি পদ্ধতি পয়েন্টকট সঙ্গে একটি টাইপ পয়েন্টকুট একত্রিত করা উচিত।
এই পয়েন্টকাটগুলি @ মনিটরের টিকা দিয়ে চিহ্নিত শ্রেণীর ভিতরে সমস্ত পাবলিক পদ্ধতিগুলি সন্ধান করার জন্য কাজ করবে:
@Pointcut("within(@org.rejeev.Monitor *)")
public void beanAnnotatedWithMonitor() {}
@Pointcut("execution(public * *(..))")
public void publicMethod() {}
@Pointcut("publicMethod() && beanAnnotatedWithMonitor()")
public void publicMethodInsideAClassMarkedWithAtMonitor() {}
প্রথম দুটিকে সংযুক্ত করে শেষ পয়েন্টকুটটি পরামর্শ দিন এবং আপনি শেষ করেছেন!
আপনি যদি আগ্রহী হন তবে আমি এখানে @AspectJ শৈলীর সাথে একটি প্রাসঙ্গিক উদাহরণ ডকুমেন্ট সহ একটি প্রতারণামূলক শীট লিখেছি ।
প্রশ্নের মধ্যে বর্ণিত হিসাবে টীকাগুলি ব্যবহার করে।
টীকা: @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>
Monitor
একটি বসন্ত হতে হবে Component
?
Component
টীকা জিনিস Weaver AspectJ মধ্যে বর্গ অন্তর্ভুক্ত আবেদন করতে স্প্রিং ধারক বলতে ব্যবহৃত হয়। ডিফল্টরূপে, স্প্রিং শুধুমাত্র এ দেখায় Controller
, Service
এবং অন্যান্য নির্দিষ্ট টীকা, কিন্তু না Aspect
।
@Component
উপর টীকা @interface
না Aspect
। কেন এটি প্রয়োজন?
@Component
টীকা এটা তোলে তাই স্প্রিং AspectJ আইওসি / ডিআই দৃষ্টিভঙ্গি ওরিয়েন্টেড সিস্টেমের সাথে এটা কম্পাইল করতে হবে। কীভাবে এটি আলাদাভাবে বলতে হয় তা আমি জানি না। docs.spring.io/spring/docs/3.2.x/spring-framework-references/…
এরকম কিছু:
@Before("execution(* com.yourpackage..*.*(..))")
public void monitor(JoinPoint jp) {
if (jp.getTarget().getClass().isAnnotationPresent(Monitor.class)) {
// perform the monitoring actions
}
}
দ্রষ্টব্য যে এই শ্রেণীর আগে আপনার অবশ্যই একই শ্রেণীর জন্য অন্য কোনও পরামর্শ নেওয়ার দরকার নেই , কারণ প্রকাশনার পরে টিকাগুলি নষ্ট হবে।
ব্যবহার
@Before("execution(* (@YourAnnotationAtClassLevel *).*(..))")
public void beforeYourAnnotation(JoinPoint proceedingJoinPoint) throws Throwable {
}
সবচেয়ে সহজ উপায় বলে মনে হচ্ছে:
@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 {
}
// perform actions after
আমরা আগে লাইনে মান ফিরে করছি যেহেতু কখনোই বলা হবে।
আপনি স্প্রিংয়ের পারফরম্যান্সমনিটরিং ইন্টারসেপ্টার ব্যবহার করতে পারেন এবং প্রোগ্রামালিভাবে একটি বিনপোস্টপ্রসেসর ব্যবহার করে পরামর্শটি নিবন্ধভুক্ত করতে পারেন।
@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;
}
}
}
বসন্তের থেকে 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 *);