(Basic grammar) On Aspect Oriented Programming (AOP)

I. Introduction

Aspect Oriented Programming is a very important concept idea, you want to write a program easy to maintain, and can be trained to understand the AOP in the actual programming reasonable use of AOP is thought necessary

Two: The basic concept of AOP

基础概念:AOP中文翻译面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。

Three: to achieve through dynamic proxy AOP

After reading the above concepts, may not know what is AOP, but we know only little from the concept of the above technical foundation to achieve AOP is pre-compiled and run-time dynamic way agents , then we come to the actual code is implemented by using dynamic proxies a simple program it

We often encounter such a scene in everyday object-oriented programming:
   the same method a number of A class method (below ClassA) must be in the same time calling the class B (log class Logger) are
as follows:

public class ClassA{

    public Logger logger;

    public ClassA(){
        logger=new Logger();
    }

    public void AFuncA(){
        //....做一些其他事情
        System.out.println("AFuncA做一些其他事情");
        //记录日志
        logger.WriteLog();
    }

    public void AFuncB(){
         //....做一些其他事情
        System.out.println("AFuncB做一些其他事情");
        //记录日志
        logger.WriteLog();
    }

    public void AFuncC(){
         //....做一些其他事情
        System.out.println("AFuncC做一些其他事情");
        //记录日志
        logger.WriteLog();
    }

}
/*
* 日志类
*/
public class Logger{

    public void WriteLog(){
        System.out.println("我是工具类Logger的WriteLog方法,我记录了日志"));
    }

}
/*
*单元测试Main方法
*/
@Test
public void TestMain(){
        ClassA classa=new ClassA();
        classa.AFuncA();
        classa.AFuncB();
        classa.AFuncC();
}

Output

   This simple example code above believe that with a little Java, C # and other object-oriented languages based Nengkanmingbai people, we wrote a class ClassA, encapsulates a utility class ClassB, then ClassA three methods are called Logger's WriteLog ()method.
   This design is obviously flawed, if we have hundreds of local projects are using this WriteLog () method to logging, once we want to replace this logging class or no longer cancel all logging, then modify the code up is very upset, obviously ClassA class Logger class had to rely on code coupling, then how do we optimize this class ClassA dependence on Logger to lift it, to solve this problem we must pull our aspect-oriented programming (AOP) of the idea.
   Optimization code is as follows: we can create a dynamic proxy factory object DynAgentFactory, and then based on the dynamic proxy object Enhancer subclass (cglib dependencies need to import) to ClassA proxy object, then the object is not instantiated directly ClassA ClassA in use, but to call the agent to call the factory object DynAgentFactory ClassA class

Specific Optimization code is as follows:

public class ClassA{

    public void AFuncA(){
        //....做一些其他事情
        System.out.println("AFuncA做一些其他事情");
    }

    public void AFuncB(){
        //....做一些其他事情
        System.out.println("AFuncB做一些其他事情");
    }

    public void AFuncC(){
        //....做一些其他事情
        System.out.println("AFuncC做一些其他事情");
    }
    //.....
}
/*
*动态代理工厂
*/
public class DynAgentFactory {

    private ClassA proClassA;
    private Logger logger;

    public DynAgentFactory(){
        AFunAgent();
        GetLogger();
    }

    public ClassA GetClassA(){
        return proClassA;
    }


    public Logger GetLogger(){
        logger=new Logger();
        return logger;
    }
    /*
    *代理ClassA对象
    *此处Enhancer类是基于子类的动态代理对象,需要导入cglib依赖(也可以定义一个接口,然后用Proxy实现基于接口的动态代理)
    */
     public void AFunAgent(){
        ClassA classA=new ClassA();
        proClassA=(ClassA) Enhancer.create(classA.getClass(), new MethodInterceptor() {
            public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
                Object obj=method.invoke(classA);
                logger.WriteLog();
                return obj;
            }
        });
    }
}
/*
* 日志类
*/
public class Logger
{
    public void WriteLog(){
        System.out.println("我是工具类Logger的WriteLog方法,我记录了日志");
    }
}
/*
*单元测试Main方法
*/
@Test
public void TestMain(){
    DynAgentFactory dynAgentFactory=new DynAgentFactory();
    dynAgentFactory.GetClassA().AFuncA();
    dynAgentFactory.GetClassA().AFuncB();
    dynAgentFactory.GetClassA().AFuncC();
}

The output and the same as before

   We can see through dynamic proxy factory object DynAgentFactory, we have achieved decoupling ClassA and Logger class, if in the future we want to remove or replace logging Logger class, only need to unify operations of DynAgentFactory in the Logger object, quite in the public part of ClassA pulled out of this notion said before: run-time dynamic proxy

Whether the above code has been perfect it? In fact, there are still some problems, that it would be building a dynamic proxy factory just simply agents of the ClassA, so if with the gradual expansion of the project, we will be adding new ClassB, ClassC ... have to use this class unified logging Logger, do we have to repeat write a BFunAgent, CFunAgent code to agent logging it, it AFunAgent, BFunAgent, CFunAgent inside the code is not on repeated yet, so we also need to continue to optimize this factory class DynAgentFactory, you can use the pan type to solve this problem

/*
*ClassA代码同上,此处省略
*/
//....
/*
*新加入的ClassB
*/
public class ClassB{

    public void BFuncA(){
        //....做一些其他事情
        System.out.println("BFuncA做一些其他事情");
    }

    public void BFuncB(){
        //....做一些其他事情
        System.out.println("BFuncB做一些其他事情");
    }

    public void BFuncC(){
        //....做一些其他事情
        System.out.println("BFuncC做一些其他事情");
    }
    //.....
}
/*
*泛型动态代理工厂
*/
public class DynAgentFactory<T> {

    private Logger logger;

    public DynAgentFactory(T _proClass){
        TFunAgent(_proClass);
        GetLogger();
    }

    private T proClass;

    public T GetProClass(){
        return proClass;
    }

    public Logger GetLogger(){
        logger=new Logger();
        return logger;
    }
    /*
    *代理ClassA对象
    *此处Enhancer类是基于子类的动态代理对象,需要导入cglib依赖(也可以定义一个接口,然后用Proxy实现基于接口的动态代理)
    *T pro:传入依赖对象
    */
    public void TFunAgent(T pro){
        proClass=(T) Enhancer.create(pro.getClass(), new MethodInterceptor() {
            public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
                Object obj=method.invoke(pro);
                logger.WriteLog();
                return obj;
            }
        });
    }
}
/*
*日志类Logger代码同上,此处省略
*/
//...
/*
*单元测试Main方法
*/
@Test
public void TestMain(){
    DynAgentFactory<ClassA> dynAgentFactory=new DynAgentFactory(new ClassA());
    dynAgentFactory.GetProClass().AFuncA();
    dynAgentFactory.GetProClass().AFuncB();
    dynAgentFactory.GetProClass().AFuncC();
    System.out.println("-------------------------------分割线------------------------------------------");
    DynAgentFactory<ClassB> dynAgentFactory2=new DynAgentFactory(new ClassB());
    dynAgentFactory2.GetProClass().BFuncA();
    dynAgentFactory2.GetProClass().BFuncB();
    dynAgentFactory2.GetProClass().BFuncC();
}

Output


After this further optimization, both ClassA, ClassB or other classes, if you want to use the Logger class logging, DynAgentFactory can be used to create the corresponding proxy object on it
> insert here a little digression: As the Java language in the pan type is completely implemented by the compiler, the JVM does not provide any support here, it is not like C # supports T t = new T () written in this way, every time it is needed to instantiate objects by means of injection into the constructor factory object were to go.

Dynamic proxies summary

Dynamic proxies art can better reduce the coupling between the codes, the code function to enhance the specificity, in addition to the global logging above, we can also use it to do some processing filters, like Universal transaction function to know the dynamic proxy, we could look back at the spring framework seen in <aop: {ADVICE NAME}> tags, these tags are not will have a deeper understanding, as a basis spring aop is dynamic proxy, only but after the breakdown of the proxy to do, by the following <aop: {ADVICE NAME}> is a spring element declares one of five in adivce

<aop:config>
   <aop:aspect id="myAspect" ref="aBean">
      <aop:pointcut id="businessService"
         expression="execution(* com.xyz.myapp.service.*.*(..))"/>
      <!-- a before advice definition -->
      <aop:before pointcut-ref="businessService" 
         method="doRequiredTask"/>
      <!-- an after advice definition -->
      <aop:after pointcut-ref="businessService" 
         method="doRequiredTask"/>
      <!-- an after-returning advice definition -->
      <!--The doRequiredTask method must have parameter named retVal -->
      <aop:after-returning pointcut-ref="businessService"
         returning="retVal"
         method="doRequiredTask"/>
      <!-- an after-throwing advice definition -->
      <!--The doRequiredTask method must have parameter named ex -->
      <aop:after-throwing pointcut-ref="businessService"
         throwing="ex"
         method="doRequiredTask"/>
      <!-- an around advice definition -->
      <aop:around pointcut-ref="businessService" 
         method="doRequiredTask"/>
   ...
   </aop:aspect>
</aop:config>
<bean id="aBean" class="...">
...
</bean>

Three: the expansion and summary

By the above simple example, we learned through dynamic proxy AOP achieve, but here we need to know is that AOP is a programming idea, is achieved through dynamic AOP proxy is only one way to achieve, we can also be achieved through AOP pre-compiler, here you have to say about the AspectJ aspect-oriented framework, AspectJ can directly modify the source code generation class during compilation.

What is AspectJ? AspectJ nor that this @AspectJ

In a search online usage of a large so-called AspectJ, AspectJ are in fact the "grammar section" tip of the iceberg AspectJ framework, AspectJ is completely independent of the existence of a Eclipse Spring launch of the project, the official description of the AspectJ is:
the Eclipse AspectJ is a seamless aspect-oriented extension to the Java ™ programming language. It is Java platform compatible easy to learn and use.

Yes, AspectJ can even be said to be an independent language, we often see in the spring with the @Aspect annotation just after Spring2.0 using AspectJ style it still essentially Spring native implementation, on this Spring point manuals are mentioned:
the @AspectJ use of Java 5 annotations, the section can be declared as regular Java classes. @AspectJ style was introduced by AspectJ project as part of the AspectJ 5 release. Spring 2.0 and AspectJ 5 uses the same notes, and use AspectJ for pointcut parsing and matching. However, AOP at runtime is still pure Spring AOP, does not depend on the AspectJ compiler or weaver (weaver).
Therefore AspectJ related notes in our common org.aspectj.lang.annotation package just use AspectJ style, as well as a full range of AspectJ weaver, it is completely independent of another set of things. As for the specific how to play I did not play too, are interested in small partner can own Baidu

Guess you like

Origin www.cnblogs.com/ruanraun/p/javaaop.html