The body of the

An overview,

In the software industry, AOP for the abbreviation of Aspect Oriented Programming, meaning: section-oriented Programming, through pre-compilation and runtime dynamic proxy to achieve unified maintenance of program functions of a technology. AOP is a continuation of OOP(object-oriented programming), a hot topic in software development, and a derivative paradigm of functional programming.

Using AOP, each part of the business logic can be isolated, thus reducing the degree of coupling between each part of the business logic, improving the reusability of the program, and improving the efficiency of development.

Summarizes the advantages of

Each part of the business logic is isolated, and the degree of coupling between services is reduced.

Improved program reusability and easier maintenance;

Improved development efficiency, less time spent adding code to the business, and reduced risk;

In fact, the essence of AOP is dynamic proxy, what is dynamic proxy?

Dynamic proxy is a technique to create proxy objects of target objects and enhance the functions of methods in the target objects when the program is running. In layman’s terms, it is the interception of a method at run time, with additional business processing done before and after the method execution, thereby enhancing the business capability of the intercepted method without embedding the original code logic.

So let’s stop with the theory and see how we can do it in code. Okay?

Practice tests truth (whether it is excellent or not)

Start with a console project, with nothing at all, and start with code from scratch. Let’s look at the project structure:

Old case, or pretend to be in user maintenance, simulation of the user to add, delete, change and check. This time I will go directly to the code, according to the structure of the project look at the code:

Add user.cs to AopModel

public class User { public string Name { get; set; } public int Age { get; set; }}Copy the code

Add iuser. cs and user.cs to AopService

IUserService.cs

public interface IUserService
{
  bool AddUser(User user);
}
Copy the code

UserService.cs

Public class UserService: IUserService {public bool AddUser(User User) {Console.WriteLine(" User added successfully "); return true; }}Copy the code

The Main method

Class Program {static void Main (string [] args) {Console. WriteLine (" = = = = = = = = original requirements = = = = = = = = = "); User user = new User { Name = "Zoe", Age = 18 }; IUserService userService = new UserService(); // add a user userservice.adduser (user); Console.ReadLine(); }}Copy the code

In this way, the project will run normally. I don’t need to take screenshots of this.

The project is working fine, but you need to add one requirement: email notification when the user is successfully added.

There are two solutions

1. Add the logic of sending emails directly to the method of adding users (I believe many partners do so, quick and easy);

If you frequently add new requirements before or after adding users, do you continue to add them? The method of adding users may become very complicated in the end, and it is not easy to maintain in the later stage. If you want to remove a feature and have to change the code back, as a programmer, you will have to fight with your product colleagues (civilized people, don’t fight); Of course, this is fine if the demand is fixed.

2. Section-oriented implementation, that is, the method can be dynamically intercepted without affecting the original code logic, and business can be added before or after the method is executed.

AOP(aspect oriented programming) was introduced into the project

Original dynamic proxy implementation;

Let’s add a proxy class as follows:

using System; using System.Collections.Generic; using System.Reflection; using System.Text; Namespace Aop {DispatchProxy public class MyProxy: DispatchProxy {public object TargetClass {get; set; } protected Override object Invoke(MethodInfo targetMethod, object[] args) {console. WriteLine(" add user "); // Invoke the old method targetMethod.Invoke(TargetClass, args); Console.WriteLine(" Execute service after adding user "); return true; }}}Copy the code

Then use the Main function directly as follows:

Class Program {static void Main(string[] args) {User User = new User {Name = "Zoe", Age = 18}; IUserService userService = new UserService(); userService.AddUser(user); Console. WriteLine (" = = = = = = = = dynamic proxy to implement new requirements = = = = = = = = = "); IUserService userService1 = dispatchProxy. Create<IUserService, MyProxy>(); (MyProxy)userService1).targetClass = new UserService(); userService1.AddUser(user); Console.ReadLine(); }}Copy the code

Dynamic proxy to achieve the function of demand, you can increase the user before or after the relevant demand processing, run to see the effect:

Third party library Castle.Core package of beauty;

As demonstrated above, the native dynamic proxy implementation is relatively cumbersome for aspect programming, such as casting, passing type operations; The commonly used Castle.Core encapsulates the dynamic proxy further, making it relatively easy to use; Define an interceptor this time:

using Castle.DynamicProxy; using System; using System.Collections.Generic; using System.Text; Namespace Aop {// Public class MyIntercept: IInterceptor {public void Intercept(IInvocation) {Console.WriteLine(" Business before adding users "); Invocation.Proceed(); // After the original method is executed Console.WriteLine(" Add user and execute service "); }}}Copy the code

Use the interceptor in the Main function, as follows:

using AopModel; using AopService; using Castle.DynamicProxy; using System; using System.Reflection; using System.Reflection.Metadata; Namespace Aop {class Program {static void Main(string[] args) {console. WriteLine("======== original requirement ========="); User user = new User { Name = "Zoe", Age = 18 }; IUserService userService = new UserService(); // add a user userservice.adduser (user); Console. WriteLine (" = = = = = = = = dynamic proxy to implement new requirements = = = = = = = = = "); IUserService userService1 = dispatchProxy. Create<IUserService, MyProxy>(); (MyProxy)userService1).targetClass = new UserService(); userService1.AddUser(user); Console. WriteLine (" = = = = = = = = = = = = = Castle. The Core way = = = = = = = = = = = = = = "); ProxyGenerator generator = new ProxyGenerator(); / / create var u = generator. Through the proxy class generator CreateInterfaceProxyWithTarget < IUserService > (new UserService (), new MyIntercept ()); u.AddUser(user); Console.ReadLine(); }}}Copy the code

The running effect is as follows:

The Autofac integration with Castle.Core is also good to use;

Autofac is already integrated with Castle.Core, which is used in MemoryCache discussions. It is easy to use, and can be enhanced by using feature annotations to block methods ofa class or interface, as described in this article.

Three, application scenarios

AOP ideas are good, but you can’t use them everywhere. You need to evaluate the need for them based on your business. The common application scenarios are as follows:

1. Security control

Typically in Web development, permissions are verified using filters or interceptors, which is where AOP ideas land; For the client program, the unified management and verification of permissions can be easily realized through the above demonstrated ways;

2. Transaction processing

I believe you have written database transaction code, the general practice is to directly open the transaction in the business method, execute, commit or rollback can be, AOP ideas can also handle this situation;

3. Exception handling

Uniform exception handling is the best option, except for special business; Usually the Web has exception filters, and client programs can use these methods;

4. Log

For now, logging should be part of the system’s functionality, and AOP unified logging is a good choice;

5. Performance statistics

The implementation performance of the method can be analyzed by monitoring the method before and after using AOP.

6. Cache processing

Caching, as mentioned last time, coupled with AOP interceptor applications, is a nice efficiency boost

7. The auxiliary service remains unchanged

The main service changes, but auxiliary requirements are added from time to time. For example, after users are added, functions such as email notification and push of new user information may be added.

conclusion

Recently a lot of people in the interview, I compiled a: Spring series bucket (1187 – page document), Java systematic data (including 2021 latest Java core knowledge, interview project and 20 years summarizes the Internet bo, e-books, etc.), a friend in need can be pay attention to the public, can obtain program are gentle little wan 】 【.