Reputation: 457
I was trying to create a sample of Intercept mechanism in JAVA. The questions I have is,
1) Why it only works with injected object but not using simple constructor ?
2) How can I intercept without CDI and using constructors only ? Because I want to use constructors with some arguments (Not default constructor).
public class StartingPoint extends HttpServlet
{
private static final long serialVersionUID = 1L;
// With CDI
@Inject
SimpleGreeting greeting;
public void doGet(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException
{
System.out.println("Started");
System.out.println(greeting.abc());
}
}
public class StartingPoint extends HttpServlet
{
private static final long serialVersionUID = 1L;
public void doGet(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException
{
// With simple constructor
SimpleGreeting greeting = new SimpleGreeting();
System.out.println("Started");
System.out.println(greeting.abc());
}
}
SimpleGreeting.java
@MyInterceptorBinding
public class SimpleGreeting
{
public SimpleGreeting()
{
}
public String abc()
{
return "Greet";
}
}
MyInterceptorBinding.java
@Inherited
@InterceptorBinding
@Retention(RUNTIME)
@Target({ METHOD, TYPE })
public @interface MyInterceptorBinding {
}
MyInterceptor.java
@Interceptor
@MyInterceptorBinding
public class MyInterceptor
{
public MyInterceptor()
{
}
@AroundInvoke
public Object log(InvocationContext context) throws Exception
{
System.out.println("Intercepted");
return context.proceed();
}
}
Upvotes: 1
Views: 1042
Reputation: 40066
I believe it is because the interception mechanism is Proxy-base. Which means, although you think you are referring to a Foo
, it is actually a proxy of Foo
, for which do the interception logic, and delegate the call to the real Foo
instance.
Hence the container will need to manage the injection of beans (so it can create the proxy and inject the proxy instead of the actual bean). If you are instantiating by yourself, there is no way the container can do such work.
Yes there is. For example for AspectJ, you can have runtime weaving to add those interception code into the classes in effect.
Upvotes: 0
Reputation: 1377
If you take a look at the javadoc : http://docs.oracle.com/javaee/6/api/javax/interceptor/InterceptorBinding.html , you will notice that @InterceptorBinding
is an annotation associated to beans (i.e instances managed by the container as EJB, managed beans, etc.) :
Interceptor bindings are intermediate annotations that may be used to associate interceptors with target beans
Upvotes: 1
Reputation: 42966
1) Why it only works with injected object but not using simple constructor ?
When the greeting is injected using CDI, there is some "magic" happening under the covers. If CDI was only capable of calling a simple constructor, it wouldn't be a very useful technology.
So if you have the following code:
@Inject
SimpleGreeting greeting;
What's effectively happening under the covers is something like this:
SimpleGreeting greeting = injectGreeting();
private SimpleGreeting injectGreeting() {
if ( /* MyInterceptorBinding annotation present on SimpleGreeting class */)
new MyInterceptor().log(context); // this prints "Intercepted"
return new SimpleGreeting();
}
2) Is there any way to intercept without CDI and using constructors only?
Technically yes, but interceptors are the easiest way. The only other way I can think of off the top of my head is a bytecode manipulation framework such as ASM.
Upvotes: 0