What Aspect Differentiates Prochaska's Behavior Change Model From Other Models?
Spring Framework is developed on 2 core concepts – Dependency Injection and Aspect Oriented Programming ( Spring AOP).
Bound AOP
We have already seen how Spring Dependency Injection works, today nosotros volition await into the core concepts of Aspect-Oriented Programming and how nosotros tin implement it using Leap Framework.
Jump AOP Overview
Most of the enterprise applications have some common crosscutting concerns that are applicable to different types of Objects and modules. Some of the common crosscutting concerns are logging, transaction management, data validation, etc.
In Object Oriented Programming, modularity of application is accomplished by Classes whereas in Aspect Oriented Programming application modularity is achieved by Aspects and they are configured to cut beyond different classes.
Bound AOP takes out the direct dependency of crosscutting tasks from classes that nosotros can't accomplish through normal object oriented programming model. For case, we tin can have a separate class for logging but again the functional classes will accept to call these methods to achieve logging beyond the awarding.
Aspect Oriented Programming Core Concepts
Earlier we dive into the implementation of Spring AOP implementation, nosotros should empathise the cadre concepts of AOP.
- Aspect: An aspect is a class that implements enterprise application concerns that cut across multiple classes, such as transaction direction. Aspects tin be a normal course configured through Spring XML configuration or we tin can use Leap AspectJ integration to define a class equally Attribute using
@Aspect
annotation. - Join Point: A join point is a specific point in the awarding such as method execution, exception treatment, changing object variable values, etc. In Spring AOP a join point is always the execution of a method.
- Advice: Advices are actions taken for a particular join point. In terms of programming, they are methods that get executed when a certain bring together point with matching pointcut is reached in the application. You can retrieve of Advices as Struts2 interceptors or Servlet Filters.
- Pointcut: Pointcut is expressions that are matched with join points to decide whether communication needs to be executed or not. Pointcut uses different kinds of expressions that are matched with the join points and Spring framework uses the AspectJ pointcut expression linguistic communication.
- Target Object: They are the object on which advices are applied. Spring AOP is implemented using runtime proxies and so this object is always a proxied object. What is means is that a subclass is created at runtime where the target method is overridden and advice are included based on their configuration.
- AOP proxy: Spring AOP implementation uses JDK dynamic proxy to create the Proxy classes with target classes and advice invocations, these are called AOP proxy classes. We tin can also use CGLIB proxy by calculation it as the dependency in the Spring AOP projection.
- Weaving: It is the process of linking aspects with other objects to create the advised proxy objects. This can be done at compile time, load time or at runtime. Spring AOP performs weaving at the runtime.
AOP Advice Types
Based on the execution strategy of advice, they are of the post-obit types.
- Before Advice: These advices runs earlier the execution of join point methods. We can use
@Before
annotation to mark an advice type as Before advice. - Later (finally) Advice: An communication that gets executed subsequently the bring together point method finishes executing, whether usually or by throwing an exception. Nosotros can create after communication using
@Later on
notation. - Later Returning Advice: Sometimes nosotros want advice methods to execute only if the join point method executes normally. We can utilize
@AfterReturning
note to mark a method as after returning advice. - Later on Throwing Advice: This advice gets executed merely when join indicate method throws exception, nosotros tin use information technology to rollback the transaction declaratively. We use
@AfterThrowing
note for this type of advice. - Effectually Advice: This is the most important and powerful advice. This advice surrounds the bring together point method and we tin also choose whether to execute the join bespeak method or not. We can write advice lawmaking that gets executed earlier and afterward the execution of the join indicate method. It is the responsibility of around advice to invoke the join indicate method and return values if the method is returning something. Nosotros utilize
@Around
annotation to create around advice methods.
The points mentioned to a higher place may sound confusing just when we will look at the implementation of Jump AOP, things will exist more clear. Let's offset creating a unproblematic Bound project with AOP implementations. Bound provides support for using AspectJ annotations to create aspects and we will exist using that for simplicity. All the above AOP annotations are defined in org.aspectj.lang.annotation
package.
Spring Tool Suite provides useful information near the aspects, so I would suggest you use it. If you are not familiar with STS, I would recommend you to have a expect at Spring MVC Tutorial where I accept explained how to use it.
Spring AOP Instance
Create a new Simple Spring Maven project and then that all the Bound Core libraries are included in the pom.xml files and we don't need to include them explicitly. Our final project will look similar the below epitome, we will look into the Spring core components and Aspect implementations in detail.
Jump AOP AspectJ Dependencies
Spring framework provides AOP support by default but since we are using AspectJ annotations for configuring aspects and communication, we would need to include them in the pom.xml file.
<project xmlns="https://maven.apache.org/POM/4.0.0" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="https://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>org.springframework.samples</groupId> <artifactId>SpringAOPExample</artifactId> <version>0.0.1-SNAPSHOT</version> <properties> <!-- Generic backdrop --> <java.version>1.6</java.version> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</projection.reporting.outputEncoding> <!-- Spring --> <spring-framework.version>four.0.two.RELEASE</spring-framework.version> <!-- Logging --> <logback.version>1.0.13</logback.version> <slf4j.version>1.7.5</slf4j.version> <!-- Test --> <junit.version>4.11</junit.version> <!-- AspectJ --> <aspectj.version>one.7.4</aspectj.version> </properties> <dependencies> <!-- Spring and Transactions --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>${spring-framework.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-tx</artifactId> <version>${spring-framework.version}</version> </dependency> <!-- Logging with SLF4J & LogBack --> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>${slf4j.version}</version> <scope>compile</scope> </dependency> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-classic</artifactId> <version>${logback.version}</version> <scope>runtime</telescopic> </dependency> <!-- AspectJ dependencies --> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjrt</artifactId> <version>${aspectj.version}</version> <telescopic>runtime</scope> </dependency> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjtools</artifactId> <version>${aspectj.version}</version> </dependency> </dependencies> </projection>
Find that I accept added aspectjrt
and aspectjtools
dependencies (version 1.vii.iv) in the projection. Also I take updated the Bound framework version to be the latest one as of engagement i.e 4.0.2.RELEASE.
Model Class
Let'southward create a elementary java bean that we will apply for our example with some additional methods.
Employee.coffee lawmaking:
package com.journaldev.bound.model; import com.journaldev.spring.attribute.Loggable; public course Employee { individual String name; public String getName() { render name; } @Loggable public void setName(String nm) { this.name=nm; } public void throwException(){ throw new RuntimeException("Dummy Exception"); } }
Did you noticed that setName() method is annotated with Loggable
note. Information technology is a custom java notation defined by us in the project. We will look into it's usage later on.
Service Grade
Let's create a service grade to work with the Employee edible bean.
EmployeeService.java lawmaking:
package com.journaldev.leap.service; import com.journaldev.spring.model.Employee; public form EmployeeService { private Employee employee; public Employee getEmployee(){ render this.employee; } public void setEmployee(Employee due east){ this.employee=e; } }
I could accept used Bound annotations to configure it as a Bound Component, simply we will utilise XML based configuration in this project. EmployeeService class is very standard and simply provides usa an access point for Employee beans.
Spring Bean Configuration with AOP
If you are using STS, yous take the option to create "Spring Bean Configuration File" and chose AOP schema namespace simply if y'all are using some other IDE, you lot can but add it in the spring edible bean configuration file.
My projection edible bean configuration file looks like below.
spring.xml:
<?xml version="1.0" encoding="UTF-viii"?> <beans xmlns="https://www.springframework.org/schema/beans" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xmlns:aop="https://www.springframework.org/schema/aop" xsi:schemaLocation="https://www.springframework.org/schema/beans https://world wide web.springframework.org/schema/beans/jump-beans-4.0.xsd https://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/leap-aop-4.0.xsd"> <!-- Enable AspectJ style of Spring AOP --> <aop:aspectj-autoproxy /> <!-- Configure Employee Bean and initialize information technology --> <bean proper noun="employee" class="com.journaldev.jump.model.Employee"> <property name="name" value="Dummy Name"></belongings> </bean> <!-- Configure EmployeeService bean --> <bean proper noun="employeeService" class="com.journaldev.spring.service.EmployeeService"> <property proper name="employee" ref="employee"></property> </bean> <!-- Configure Aspect Beans, without this Aspects advices wont execute --> <bean name="employeeAspect" class="com.journaldev.spring.aspect.EmployeeAspect" /> <bean proper noun="employeeAspectPointcut" course="com.journaldev.bound.aspect.EmployeeAspectPointcut" /> <bean name="employeeAspectJoinPoint" class="com.journaldev.jump.aspect.EmployeeAspectJoinPoint" /> <bean proper noun="employeeAfterAspect" class="com.journaldev.spring.aspect.EmployeeAfterAspect" /> <edible bean name="employeeAroundAspect" form="com.journaldev.spring.aspect.EmployeeAroundAspect" /> <edible bean proper noun="employeeAnnotationAspect" course="com.journaldev.bound.attribute.EmployeeAnnotationAspect" /> </beans>
For using Leap AOP in Spring beans, nosotros need to do the following:
- Declare AOP namespace like xmlns:aop="https://world wide web.springframework.org/schema/aop"
- Add aop:aspectj-autoproxy chemical element to enable Spring AspectJ support with auto proxy at runtime
- Configure Attribute classes as other Jump beans
Yous can see that I have a lot of aspects divers in the spring edible bean configuration file, it's time to look into them i by one.
Spring AOP Earlier Attribute Example
EmployeeAspect.coffee code:
bundle com.journaldev.spring.attribute; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Earlier; @Aspect public class EmployeeAspect { @Before("execution(public String getName())") public void getNameAdvice(){ System.out.println("Executing Advice on getName()"); } @Before("execution(* com.journaldev.spring.service.*.become*())") public void getAllAdvice(){ System.out.println("Service method getter called"); } }
Important points in higher up aspect class are:
- Aspect classes are required to accept
@Aspect
notation. - @Before notation is used to create Before communication
- The string parameter passed in the
@Earlier
annotation is the Pointcut expression - getNameAdvice() communication will execute for any Spring Bean method with signature
public Cord getName()
. This is a very important point to remember, if we will create Employee bean using new operator the advices volition not exist applied. Simply when we will utilize ApplicationContext to get the edible bean, advices will be applied. - We can use asterisk (*) equally wild card in Pointcut expressions, getAllAdvice() volition be applied for all the classes in
com.journaldev.leap.service
bundle whose name starts withbecome
and doesn't accept any arguments.
We volition look at the advice in activity in a exam class subsequently nosotros take looked into all the different types of advices.
Leap AOP Pointcut Methods and Reuse
Sometimes we take to utilise same Pointcut expression at multiple places, we tin create an empty method with @Pointcut
annotation and and so use information technology equally an expression in the advices.
EmployeeAspectPointcut.java code:
package com.journaldev.spring.attribute; import org.aspectj.lang.note.Aspect; import org.aspectj.lang.notation.Earlier; import org.aspectj.lang.annotation.Pointcut; @Aspect public class EmployeeAspectPointcut { @Before("getNamePointcut()") public void loggingAdvice(){ System.out.println("Executing loggingAdvice on getName()"); } @Before("getNamePointcut()") public void secondAdvice(){ Organization.out.println("Executing secondAdvice on getName()"); } @Pointcut("execution(public String getName())") public void getNamePointcut(){} @Before("allMethodsPointcut()") public void allServiceMethodsAdvice(){ Arrangement.out.println("Before executing service method"); } //Pointcut to execute on all the methods of classes in a bundle @Pointcut("within(com.journaldev.jump.service.*)") public void allMethodsPointcut(){} }
Above instance is very articulate, rather than expression we are using method name in the advice note argument.
Spring AOP JoinPoint and Communication Arguments
We tin use JoinPoint as a parameter in the advice methods and using information technology get the method signature or the target object.
We can employ args()
expression in the pointcut to exist applied to whatever method that matches the statement design. If nosotros use this, then nosotros need to utilize the same name in the advice method from where the argument type is determined. Nosotros tin use Generic objects also in the advice arguments.
EmployeeAspectJoinPoint.coffee lawmaking:
package com.journaldev.spring.aspect; import java.util.Arrays; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.notation.Attribute; import org.aspectj.lang.annotation.Earlier; @Aspect public form EmployeeAspectJoinPoint { @Earlier("execution(public void com.journaldev.spring.model..set*(*))") public void loggingAdvice(JoinPoint joinPoint){ Organisation.out.println("Before running loggingAdvice on method="+joinPoint.toString()); System.out.println("Agruments Passed=" + Arrays.toString(joinPoint.getArgs())); } //Communication arguments, volition be practical to bean methods with single String argument @Before("args(name)") public void logStringArguments(Cord name){ Organisation.out.println("String argument passed="+proper name); } }
Leap AOP Later on Advice Example
Let's wait at a uncomplicated aspect form with an case of Later, After Throwing and After Returning communication.
EmployeeAfterAspect.java lawmaking:
package com.journaldev.spring.aspect; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.annotation.After; import org.aspectj.lang.note.AfterReturning; import org.aspectj.lang.note.AfterThrowing; import org.aspectj.lang.annotation.Aspect; @Aspect public class EmployeeAfterAspect { @After("args(name)") public void logStringArguments(Cord name){ Arrangement.out.println("Running Later Advice. String argument passed="+name); } @AfterThrowing("inside(com.journaldev.bound.model.Employee)") public void logExceptions(JoinPoint joinPoint){ System.out.println("Exception thrown in Employee Method="+joinPoint.toString()); } @AfterReturning(pointcut="execution(* getName())", returning="returnString") public void getNameReturningAdvice(String returnString){ Organization.out.println("getNameReturningAdvice executed. Returned String="+returnString); } }
Nosotros can apply within
in pointcut expression to apply the advice to all the methods in the course. We can use @AfterReturning advice to get the object returned past the advised method.
We take throwException() method in the Employee bean to showcase the use of Later Throwing advice.
Spring AOP Effectually Aspect Case
Equally explained earlier, we can use Around aspect to cut the method execution earlier and after. We can use information technology to command whether the advised method volition execute or not. Nosotros tin can also inspect the returned value and alter it. This is the virtually powerful advice and needs to be applied properly.
EmployeeAroundAspect.java lawmaking:
package com.journaldev.bound.aspect; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.notation.Around; import org.aspectj.lang.annotation.Attribute; @Aspect public class EmployeeAroundAspect { @Around("execution(* com.journaldev.leap.model.Employee.getName())") public Object employeeAroundAdvice(ProceedingJoinPoint proceedingJoinPoint){ Organisation.out.println("Before invoking getName() method"); Object value = null; try { value = proceedingJoinPoint.keep(); } catch (Throwable e) { e.printStackTrace(); } System.out.println("After invoking getName() method. Return value="+value); render value; } }
Around advice are always required to accept ProceedingJoinPoint as an argument and nosotros should use it's proceed() method to invoke the target object advised method.
If advised method is returning something, it's advice responsibility to return it to the caller program. For void methods, advice method tin return naught.
Since around advice cutting effectually the brash method, we can command the input and output of the method too as it's execution behavior.
Spring Advice with Custom Notation Pointcut
If you look at all the above advice pointcut expressions, there are chances that they get applied to another beans where it'south non intended. For example, someone tin ascertain a new bound edible bean with getName() method and the advice volition start getting practical to that even though information technology was non intended. That's why we should go on the scope of pointcut expression equally narrow every bit possible.
An alternative approach is to create a custom note and annotate the methods where we want the advice to exist applied. This is the purpose of having Employee setName() method annotated with @Loggable annotation.
Spring Framework @Transactional annotation is a bully example of this arroyo for Jump Transaction Direction.
Loggable.java code:
package com.journaldev.spring.aspect; public @interface Loggable { }
EmployeeAnnotationAspect.java lawmaking:
bundle com.journaldev.spring.attribute; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.note.Earlier; @Aspect public class EmployeeAnnotationAspect { @Earlier("@annotation(com.journaldev.spring.aspect.Loggable)") public void myAdvice(){ Arrangement.out.println("Executing myAdvice!!"); } }
The myAdvice() method will communication only setName() method. This is a very prophylactic arroyo and whenever we desire to apply the advice on any method, all we need is to annotate information technology with Loggable annotation.
Spring AOP XML Configuration
I always prefer annotation just nosotros also have the pick to configure aspects in the spring configuration file. For example, let'southward say we have a class as below.
EmployeeXMLConfigAspect.coffee code:
package com.journaldev.spring.attribute; import org.aspectj.lang.ProceedingJoinPoint; public class EmployeeXMLConfigAspect { public Object employeeAroundAdvice(ProceedingJoinPoint proceedingJoinPoint){ System.out.println("EmployeeXMLConfigAspect:: Before invoking getName() method"); Object value = naught; try { value = proceedingJoinPoint.go on(); } take hold of (Throwable e) { e.printStackTrace(); } System.out.println("EmployeeXMLConfigAspect:: Afterwards invoking getName() method. Render value="+value); render value; } }
We tin configure it by including the following configuration in the Bound Bean config file.
<bean name="employeeXMLConfigAspect" class="com.journaldev.spring.aspect.EmployeeXMLConfigAspect" /> <!-- Spring AOP XML Configuration --> <aop:config> <aop:aspect ref="employeeXMLConfigAspect" id="employeeXMLConfigAspectID" order="i"> <aop:pointcut expression="execution(* com.journaldev.bound.model.Employee.getName())" id="getNamePointcut"/> <aop:around method="employeeAroundAdvice" pointcut-ref="getNamePointcut" arg-names="proceedingJoinPoint"/> </aop:aspect> </aop:config>
AOP xml config elements purpose is clear from their name, so I won't go into much detail nigh it.
Spring AOP Case
Let's have a unproblematic Spring program and run into how all these aspects cut through the bean methods.
SpringMain.coffee code:
package com.journaldev.leap.principal; import org.springframework.context.support.ClassPathXmlApplicationContext; import com.journaldev.leap.service.EmployeeService; public class SpringMain { public static void primary(String[] args) { ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("jump.xml"); EmployeeService employeeService = ctx.getBean("employeeService", EmployeeService.class); System.out.println(employeeService.getEmployee().getName()); employeeService.getEmployee().setName("Pankaj"); employeeService.getEmployee().throwException(); ctx.shut(); } }
Now when we execute the in a higher place programme, nosotros go the following output.
Mar 20, 2014 8:fifty:09 PM org.springframework.context.support.ClassPathXmlApplicationContext prepareRefresh INFO: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@4b9af9a9: startup appointment [Thu Mar twenty 20:l:09 PDT 2014]; root of context hierarchy Mar 20, 2014 8:50:09 PM org.springframework.beans.manufacturing plant.xml.XmlBeanDefinitionReader loadBeanDefinitions INFO: Loading XML edible bean definitions from class path resources [bound.xml] Service method getter called Before executing service method EmployeeXMLConfigAspect:: Before invoking getName() method Executing Advice on getName() Executing loggingAdvice on getName() Executing secondAdvice on getName() Before invoking getName() method Later invoking getName() method. Return value=Dummy Proper name getNameReturningAdvice executed. Returned String=Dummy Name EmployeeXMLConfigAspect:: After invoking getName() method. Return value=Dummy Proper name Dummy Proper name Service method getter called Earlier executing service method String argument passed=Pankaj Before running loggingAdvice on method=execution(void com.journaldev.spring.model.Employee.setName(Cord)) Agruments Passed=[Pankaj] Executing myAdvice!! Running After Advice. String statement passed=Pankaj Service method getter chosen Before executing service method Exception thrown in Employee Method=execution(void com.journaldev.leap.model.Employee.throwException()) Exception in thread "main" java.lang.RuntimeException: Dummy Exception at com.journaldev.spring.model.Employee.throwException(Employee.coffee:19) at com.journaldev.spring.model.Employee$$FastClassBySpringCGLIB$$da2dc051.invoke(<generated>) at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204) at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:711) at org.springframework.aop.framework.ReflectiveMethodInvocation.go along(ReflectiveMethodInvocation.java:157) at org.springframework.aop.aspectj.AspectJAfterThrowingAdvice.invoke(AspectJAfterThrowingAdvice.java:58) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92) at org.springframework.aop.framework.ReflectiveMethodInvocation.go along(ReflectiveMethodInvocation.coffee:179) at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:644) at com.journaldev.jump.model.Employee$$EnhancerBySpringCGLIB$$3f881964.throwException(<generated>) at com.journaldev.spring.main.SpringMain.main(SpringMain.coffee:17)
Yous tin can see that advices are getting executed one by one based on their pointcut configurations. You should configure them one by one to avoid confusion.
That's all for Spring AOP Example Tutorial, I hope you learned the basics of AOP with Bound and can learn more from examples. Download the sample projection from below link and play around with it.
Source: https://www.journaldev.com/2583/spring-aop-example-tutorial-aspect-advice-pointcut-joinpoint-annotations
Posted by: diassplight.blogspot.com
0 Response to "What Aspect Differentiates Prochaska's Behavior Change Model From Other Models?"
Post a Comment