Getting started with spring (2) AOP

Following the above.

        Today's main study is AOP

        1. What is AOP?

            Aspect-Oriented Programming, aspect-oriented programming.

            For example, when we go to the market to buy vegetables, in order to prevent pesticide residues in the vegetables sold by the merchants, we need to carry a calibration tester with us. Every time we buy a vegetable, we need to check it manually. When we use AOP, we only need to go to buy vegetables, AOP automatically helps us to complete the detection of pesticide residues.

            In our Javabean, we need to operate a method, like adding a user. Before adding a user, we need to verify the permissions. After adding a user, we need to do a post-event logging. If we need to do this for each method, we will It will be a big project. When we don't need this permission one day, we need to delete one by one. Thinking about it, it will collapse. So have we extracted the log records during the permission checksum? AOP provides us with such a method.

        Second, the benefits of using AOP

        1. The logging code is separated from the real business logic code 

        2. The general system functions (log recording, permission verification) are highly modularized 

        3. The function of business logic has become more concise, only including the code of business logic 

        4. AOP can mix and execute system functions (logging) with business logic functions

        Three, two underlying implementations of AOP

        1. Dynamic proxy

            1.1 What is a proxy

                Principle of the proxy design pattern: wrap the original object with a proxy object, and then replace the original object with the proxy object. Any call to the original object goes through the proxy object. The proxy object decides whether and when to route method calls to the original on the object.

            1.2 Static proxy

@Override
    public boolean update(User user) {
        System.out.println("Execute permission check, log record......");
        return userService.update(user);
    }

            Manually add a proxy method for each class. If there are many classes, it will be a huge project, so we use the dynamic proxy method

        1.3 The benefits of dynamic proxies

            We can dynamically generate a Proxy that holds the original object and implements the proxy interface while the system is running, while "implanting" our general logic (logs, permissions, etc.). 

        Dynamic proxies can achieve the same functions as static proxies, the only difference is that the creation of these proxies is automatic and generated when the system is running. This eliminates the need to create a proxy for each original object. 

        Next, let's look at two implementations of dynamic proxy: JDK dynamic proxy and CGLIB dynamic proxy

        2. JDK dynamic proxy

        2.1 Create maven project, guide package

<dependency>
    <groupId>aopalliance</groupId>
    <artifactId>aopalliance</artifactId>
    <version>1.0</version>
</dependency>
<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjweaver</artifactId>
    <version>1.6.8</version>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-aop</artifactId>
    <version>4.2.4.RELEASE</version>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-aspects</artifactId>
    <version>4.2.4.RELEASE</version>
</dependency>

           2.2 Define the interface and implementation class

public interface UserService {
	
	public String getbyid();
	public void add();
	public void delete();
	public void update();
	public void batch();
}
public class UserServiceImpl implements UserService {

	@Override
	public void add() {
		System.out.println("Execute specific business logic: add...");

	}

	@Override
	public String getbyid() {
		System.out.println("Execute specific business logic: getbyid...");
		return null;
	}

	@Override
	public void delete() {
		System.out.println("Execute specific business logic: delete...");

	}

	@Override
	public void update() {
		System.out.println("Execute specific business logic: update...");

	}

	@Override
	public void batch() {
		System.out.println("Execute specific business logic: batch...");

	}

}

        2.3. Define logic enhancement (aspect class: encapsulate enhancement logic)

public class SecurityAspect {
	//check logic
	public void check(){
		System.out.println("Check permissions............");
		
	}
}

        2.4. Create his proxy object for the original object

//create proxy object
public class ProxyFactory implements InvocationHandler {

		// target
		private Object msg;
	
		public ProxyFactory(Object msg) {
			super();
			this.msg = msg;
		}

	@Override
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		// Get the aspect class and perform aspect enhancement
		SecurityAspect securityAspect = new SecurityAspect();
		securityAspect.check();
		// Execute the target object method
		Object invoke = method.invoke(msg, args);
		return invoke;
	}

	// create proxy object
	public Object getproxy() {

		return Proxy.newProxyInstance(msg.getClass().getClassLoader(),
				msg.getClass().getInterfaces(), this);
	}

}

            2.5, create a test class

@Test
	public void testName2() throws Exception {
		UserService userService = new UserServiceImpl();
		UserService user = (UserService) new ProxyFactory(userService).getproxy();
		user.add();
	}

        2.6 Existing problems

                There is a problem with using the built-in Proxy (JDK dynamic proxy) to implement dynamic proxy: the class to be proxied must implement the interface, and there is no way to complete the dynamic proxy without implementing the interface.

        3. CGLIB dynamic proxy

            cglib inherits the proxied class (UserServiceImpl), rewrites methods, weaves in notifications, dynamically generates bytecodes and runs them. Because of inheritance, there is no way for final classes to be dynamically proxied.

            3.1 Define our target class (no need to implement the interface)

public class UserCglib {
	public void show(String string){
		System.out.println("target class method"+string);
	}
}

        3.2. Defining our Aspects

public class UserAspct {
	public void writelog(){
		System.out.println("I am the aspect control object");
		
	}
}

        3.3. Define dynamic proxy

public class CglibPorxyFactory   implements MethodInterceptor {

	// target class
	private  Object msg;
	// logic enhancement
	@Override
	public Object intercept(Object o, Method method, Object[] objects, MethodProxy proxy) throws Throwable {
		//Get the interception class and execute the interception method
		UserAspct userAspct = new UserAspct();
		userAspct.writelog();
		//Get the target class and execute the target method
		Object invokeSuper = proxy.invokeSuper(o, objects);
		return invokeSuper;
	}
	//Get the proxy object
	public Object getproxy(Object msg) {
		this.msg=msg;
		Enhancer enhancer = new Enhancer();
		enhancer.setSuperclass(msg.getClass());
		enhancer.setCallback(this);
		Object create = enhancer.create();
		return create;
	}
}

        3.4. Test class

@Test
	public void testName() throws Exception {
			UserCglib getproxy = (UserCglib) new CglibPorxyFactory().getproxy(new UserCglib());
			getproxy.show("====================>Ozawa");
		
	}

            4. Terminology in AOP

                Aspect: A special object whose cross-cutting logic is modularized. i.e. it is a class: like LogAspect 

                Advice: work that must be done in the aspect. i.e. it is a method in the class: like writeLog() 

                Target class (target): the object to be notified of the enhancement 

                Proxy class (proxy): notify the target class of the object generated after the enhancement is applied 

                Pointcut: The definition of the "place" in the aspect where the notification executes 

                JoinPoint: The execution point that matches the pointcut: such as all methods in the target class getUserId()

            

            5. AOP is implemented based on xml configuration

                1. Spring develops AOP based on xml

                1.1 Create interface and implementation class

public interface UserService {
	
	public String getbyid();
	public void add();
	public String delete();
	public void update();
	public void batch();
}
public class UserServiceImpl implements UserService {

	@Override
	public void add() {
		System.out.println("Execute specific business logic: add...");

	}

	@Override
	public String getbyid() {
		System.out.println("Execute specific business logic: getbyid...");
//		System.out.println(1/0);
		return null;
	}

	@Override
	public String delete() {
		System.out.println("Execute specific business logic: delete...");
		return "big data";
		
//		System.out.println(1/0);
	}

	@Override
	public void update() {
		System.out.println("Execute specific business logic: update...");
//		System.out.println(1/0);
	}

	@Override
	public void batch() {
		System.out.println("Execute specific business logic: batch...");
		
	}

}

            1.2, define the aspect class

public class XmlAspect {
	
	public void beforAspect(JoinPoint jp  ){
		System.out.println(jp.getSignature().getName());
		System.out.println("I am the front, I want to execute first..........");
	}
	public void afterAspect(){
		System.out.println("I am a post method, I want to execute it later..........");
	}
	public void afterReturningAspect(JoinPoint jp,Object obj){
		System.out.println(obj);
		System.out.println("I am the return method, I will execute it regardless of right or wrong..........");
	}
	public void exceptionAspect(Exception ex){
		System.out.println(ex);
		System.out.println("I am reporting an error, if there is an error, I will execute it..........");
	}
	public Object aroundAspect( ProceedingJoinPoint jp ) throws Throwable{
		System.out.println("I am before the surround notification................................");
		Object proceed = jp.proceed();
		
		System.out.println("I am after the surround notification................................");
		return proceed;
	}

}

        1.3 Configure the target class, aspect class, and configure the core file in the Spring container

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:c="http://www.springframework.org/schema/c"
	xmlns:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context"
	xmlns:aop="http://www.springframework.org/schema/aop"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd
		http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.2.xsd">


	<!-- Register target and aspect objects -->
	<bean id="userserv" class="cn.itcast.dao.xml.UserServiceImpl"></bean>

	<bean id="xmlaspect" class="cn.itcast.dao.xml.XmlAspect"></bean>
	<!-- Configure spring core configuration file: configure entry point, notification, aspect-->
	<aop:config>
		<!-- Pointcut Configuration -->
		<aop:pointcut expression="execution(* *.add*(..))" id="atter1" />
		<aop:pointcut expression="execution(* *.getbyid*(..))"
			id="atter2" />
		<aop:pointcut expression="execution(* *.delete*(..))" id="atter3"   />
		<aop:pointcut expression="execution(* *.update*(..))" id="atter4" />
		<aop:pointcut expression="execution(* *.batch*(..))" id="atter5" />

		<!-- Aspect Configuration-->
		<aop:aspect ref="xmlaspect">
			<!-- Pre-notification configuration-->
			<aop:before method="beforAspect" pointcut-ref="atter1" />
			<!-- Post notification -->
			<aop:after method="afterAspect" pointcut-ref="atter2" />
			<!-- return notification-->
			<aop:after-returning method="afterReturningAspect"
				pointcut-ref="atter3"  returning="obj" />
			<!-- Error notification-->
			<aop:after-throwing method="exceptionAspect"
				pointcut-ref="atter4"  throwing="ex" />
			<!-- Surround Notification -->
			<aop:around method="aroundAspect" pointcut-ref="atter5" />
		</aop:aspect>
	</aop:config>


</beans>

        1.4 Test class

    

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext-aop-xml.xml")
public class Xmltest {

	@Autowired//Get the target proxy object in the spring container
	private UserService service;

	@Test
	public void testName() throws Exception {
		service.add();
//		service.getbyid();
//		service.delete();
//		service.update();
//		service.batch();

	}

}

                6. Implementation of AOP based on annotations

                1. Enable spring annotation scanning and enable automatic proxy for aop annotations

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:c="http://www.springframework.org/schema/c"
	xmlns:p="http://www.springframework.org/schema/p"
	xmlns:aop="http://www.springframework.org/schema/aop"
	xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd
		http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.2.xsd">
		
<!-- Scan annotation-->
		<context:component-scan base-package="cn.itcast.spring.annotation"></context:component-scan>
<!-- Enable automatic proxy -->
		<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
</beans>

                2. Define the interface and the implementation class

    

public interface UserService {
	
	public String getbyid();
	public void add();
	public String delete();
	public void update();
	public void batch();
}
@Service//Place this class in the Spring container
public class UserServiceImpl implements UserService {

	@Override
	public void add() {
		System.out.println("Execute specific business logic: add...");

	}

	@Override
	public String getbyid() {
		System.out.println("Execute specific business logic: getbyid...");
//		System.out.println(1/0);
		return null;
	}

	@Override
	public String delete() {
		System.out.println("Execute specific business logic: delete...");
//		System.out.println(1/0);
		return "big data";
	}

	@Override
	public void update() {
		System.out.println("Execute specific business logic: update...");
//		System.out.println(1/0);
	}

	@Override
	public void batch() {
		System.out.println("Execute specific business logic: batch...");
		
	}

}

                3. Define the aspect class

@Component
@Aspect
public class AspectaAnnotation {
	
	@Before(value = "execution(* *.add*(..))")
	public void beforAspect(JoinPoint jp  ){
		System.out.println(jp.getSignature().getName());
		System.out.println("I am the front, I want to execute first..........");
	}
	
	@After(value = "execution(* *.getbyid*(..))")
	public void afterAspect(){
		System.out.println("I am the post method, I will execute it regardless of right or wrong..........");
	}
	
	
	
	
	@AfterReturning(value="execution(* *.delete*(..))",returning="obj"   )
	public void afterReturningAspect(JoinPoint jp,Object obj){
		System.out.println(obj);
		System.out.println("I am the return method,................................");
	}
	
	
	@AfterThrowing(value="execution(* *.update*(..))",throwing="ex")
	public void exceptionAspect(Exception ex){
		System.out.println(ex);
		System.out.println("I am reporting an error, if there is an error, I will execute it..........");
	}
	
	
	
	@Around(value = "execution(* *.batch*(..))")
	public Object aroundAspect( ProceedingJoinPoint jp ) throws Throwable{
		System.out.println("I am before the surround notification................................");
		Object proceed = jp.proceed();
		
		System.out.println("I am after the surround notification................................");
		return proceed;
	}
	
	
}

                4. Test

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext-aop-annotation.xml")
public class Annotationtest {
	@Autowired
	private UserService service;
	@Test
	public void testName() throws Exception {
//		service.add();
//	service.getbyid();
//	service.delete();
//		service.update();
		service.batch();
	}

}


            



Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325762883&siteId=291194637