2024-07-12
한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina
Proxy means that an object A can have the same behavior as another object B by holding it. In order to open the protocol to the outside world, B often implements an interface, and A will also implement the interface. However, B is a "real" implementation class, while A is more "virtual". It borrows B's methods to implement the interface methods. Although A is a "pseudo-army", it can enhance B and do other things before and after calling B's methods. Spring AOP uses dynamic proxies to complete the dynamic "weaving" of code.
The benefits of using a proxy are more than that. If a project relies on an interface provided by another project, but the interface of the other project is unstable and the protocol is often changed, a proxy can be used. When the interface changes, only the proxy needs to be modified, and there is no need to modify the business code one by one. In this sense, we can do this for all external interfaces, so as to prevent external code from invading our code. This is called defensive programming. There may be many other applications of proxies.
In the above example, class A is hard-coded to hold B, which is a static proxy of B. If the object of A's proxy is uncertain, it is a dynamic proxy. There are currently two common implementations of dynamic proxy, jdk dynamic proxy and cglib dynamic proxy.
Static proxy is a design pattern, a type of proxy pattern. In static proxy, the proxy class is defined before the program runs, and the relationship between the proxy class and the proxied class is determined during compilation. This means that the proxy class and the proxied class implement the same interface or inherit the same parent class. The proxy class holds an instance of the proxied class and calls the proxied class's methods in its own methods. At the same time, it can add some of its own operations before and after the call, such as logging, permission checking, transaction processing, etc.
Static proxy has three components: abstract interface, proxy class, and proxied class. The implementation example is as follows:
- public interface TargetInteface {
- void method1();
- void method2();
- int method3(Integer i);
- }
- public class TargetProxy implements TargetInteface {
-
- private Target target =new Target();
- @Override
- public void method1() {
- System.out.println("执行方法前...");
- target.method1();
- System.out.println("执行方法后...");
- }
-
- @Override
- public void method2() {
- System.out.println("执行方法前...");
- target.method2();
- System.out.println("执行方法后...");
- }
-
- @Override
- public int method3(Integer i) {
- System.out.println("执行方法前...");
- int method3 = target.method3(i);
- System.out.println("执行方法后...");
- return method3;
- }
- }
- public class Target implements TargetInteface {
- @Override
- public void method1() {
- System.out.println(" Target method1 running ...");
- }
-
- @Override
- public void method2() {
- System.out.println("Target method2 running ...");
- }
-
- @Override
- public int method3(Integer i) {
- System.out.println("Target method3 running ...");
- return i;
- }
- }
- public class TargetUser {
-
- public static void main(String[] args) {
- TargetInteface target = new TargetProxy();
- target.method1();
- System.out.println("-----------------------------");
- target.method2();
- System.out.println("-----------------------------");
- System.out.println(target.method3(3));
- }
- }
Result output:
Before executing the method...
Target method1 running ...
After executing the method...
-----------------------------
Before executing the method...
Target method2 running ...
After executing the method...
-----------------------------
Before executing the method...
Target method3 running ...
After executing the method...
3
It is not difficult to see from the implementation of static proxy that the advantages of static proxy are simple implementation and easy to understand. But its disadvantages are also obvious, that is, every time you need to add proxy function to a new class, you need to manually create a new proxy class, which will lead to a sharp increase in the number of classes and the maintenance cost. At the same time, the degree of coupling between the proxy class and the proxied class is too high. When the method is added, deleted, or modified in the proxied class, the corresponding method must also be added, deleted, or modified in the proxy class, which increases the maintenance cost of the code. Another problem is that when the proxy object proxies the implementation classes of multiple target interfaces, different methods must appear in multiple implementation classes. Since the proxy object must implement the same interface as the target object (actually an inclusion relationship), it is necessary to write many methods, which is extremely easy to cause bloated and difficult to maintain code.
The core idea of dynamic proxy is to indirectly access the original object through the proxy object without modifying the original object code, and perform additional operations before and after the access.
The implementation principle of dynamic proxy is mainly based on Java's reflection mechanism. When using dynamic proxy, you need to define an interface or a group of interfaces that define the behavior of the proxy class (the proxy object). Then, you need to write an implementationInvocationHandler
The class of the interface contains the logic executed before and after the method call of the proxy object.Proxy.newProxyInstance()
method, passing in the interface's class loader, interface array, andInvocationHandler
Object, Java will dynamically generate a proxy class that implements the specified interface at runtime and delegate method calls toInvocationHandler
When you call a method on a proxy object, you are actually callingInvocationHandler
Interfaceinvoke()
Method, in which some preprocessing logic can be executed according to the method name, parameters and other information, and then the corresponding method of the proxied object can be called through reflection.
Next, we will introduce two dynamic proxies: JDK Proxy and CGLib
JDK Proxy dynamically generates proxy classes through Java's reflection mechanism. Specifically,Proxy
Class will useProxyGenerator
Class (although this class is not a public API, it is the key to implementing dynamic proxy in JDK) to generate the bytecode of the proxy class and load it into the JVM. The generated proxy class inherits fromjava.lang.reflect.Proxy
Class and implement the specified interface. In the proxy class method, it will callInvocationHandler
ofinvoke
Method, forwards the method call to the processor for processing.
In addition, to improve performance, JDK Proxy also provides a caching mechanism for caching the Class objects of the generated proxy classes. In this way, when you need to create a proxy object of the same type, you can directly obtain the Class object of the proxy class from the cache without regenerating it. Caching is done throughWeakCache
Class, which uses weak references to cache objects so that the cache items that are no longer in use can be automatically cleaned up when the JVM performs garbage collection.
- public interface TargetInteface {
- void method1();
- void method2();
- int method3(Integer i);
- }
- public class Target implements TargetInteface {
- @Override
- public void method1() {
- System.out.println("method1 running ...");
- }
-
- @Override
- public void method2() {
- System.out.println("method2 running ...");
- }
-
- @Override
- public int method3(Integer i) {
- System.out.println("method3 running ...");
- return i;
- }
- }
InvocationHandler
interface, and rewriteinvoke
Method.invoke
In the method, you can add custom logic, such as logging, permission checking, etc., and call the method of the original class through reflection.Proxy.newProxyInstance
Method, passing in the class loader, interface array, andInvocationHandler
Instance to dynamically generate a proxy object. This method returns a proxy class instance that implements the specified interface.- public class TargetProxy {
- public static <T> Object getTarget(T t) {
- //新构建了一个 新的 代理类的对象
- return Proxy.newProxyInstance(t.getClass().getClassLoader(), t.getClass().getInterfaces(), new InvocationHandler() {
- @Override
- public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
- // proxy就是目标对象t,method就是调用目标对象中方法,args就是调用目标对象中方法的参数。
- //比如说:代理对象.method1(),这时proxy就是目标类,method1就是method,args就是method1方法参数。
- System.out.println("执行方法前...");
- Object invoke = method.invoke(t, args);
- System.out.println("执行方法后...");
- return invoke;
- }
- });
- }
- }
InvocationHandler
ofinvoke
method, in which the custom logic is executed and then the method of the original class is called.- public class TargetUser {
-
- public static void main(String[] args) {
- TargetInteface target = (TargetInteface) TargetProxy.getTarget(new Target());
- target.method1();
- System.out.println("-----------------------------");
- target.method2();
- System.out.println("-----------------------------");
- System.out.println(target.method3(3));
- }
- }
Result output:
Before executing the method...
method1 running ...
After executing the method...
-----------------------------
Before executing the method...
method2 running ...
After executing the method...
-----------------------------
Before executing the method...
method3 running ...
After executing the method...
3
MethodInterceptor
The interface is used to define a method interceptor, which executes custom logic before and after the method call of the proxy object, such as preprocessing, postprocessing, exception handling, etc.- import net.sf.cglib.proxy.Enhancer;
- import net.sf.cglib.proxy.MethodInterceptor;
- import net.sf.cglib.proxy.MethodProxy;
- import java.lang.reflect.Method;
- public class Target {
- public void method1() {
- System.out.println("method1 running ...");
- }
-
- public void method2() {
- System.out.println("method2 running ...");
- }
-
- public int method3(Integer i) {
- System.out.println("method3 running ...");
- return i;
- }
- }
MethodInterceptor
Interface class and overrideintercept
Method. Write the proxy logic in this method.Enhancer
class to create a proxy object. You need to set the class to be proxied (throughsetSuperclass
method) and callbacks (viasetCallback
Method sets the MethodInterceptor implementation class).- public class TargetProxy {
- public static <T> Object getProxy(T t) {
- Enhancer en = new Enhancer(); //帮我们生成代理对象
- en.setSuperclass(t.getClass());//设置要代理的目标类
- en.setCallback(new MethodInterceptor() {//代理要做什么
- @Override
- public Object intercept(Object object, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
- System.out.println("执行方法前。。。");
- //调用原有方法
- Object invoke = methodProxy.invokeSuper(object, args);
- // Object invoke = method.invoke(t, args);// 作用等同与上面。
- System.out.println("执行方法后。。。");
- return invoke;
- }
- });
- return en.create();
- }
- }
intercept
Delegate logic in methods.- public class TargetUser {
-
- public static void main(String[] args) {
- Target target = (Target) TargetProxy.getProxy(new Target());
- System.out.println(target.getClass().getName());
- target.method1();
- }
-
- }
Result output:
com.heaboy.aopdemo.cglibproxy.TargetEnhancerByCGLIBf9f41fb8
Before executing the method...
method1 running ...
After executing the method...
advantage:
shortcoming:
Proxy object type:JDK Proxy can only proxy classes that implement interfaces; while CGLib can directly proxy ordinary classes.
performance:CGLib generates subclasses of the proxy class at runtime, and its performance is generally considered to be slightly better than JDK Proxy. However, in most scenarios, this performance difference is not significant.
scenes to be used:If the target object already implements the interface, using JDK Proxy is a simple and straightforward choice. If you need to proxy a class that does not implement the interface, you must use CGLib.
rely:JDK Proxy does not require additional dependencies because it is part of the Java core library; CGLib requires adding the CGLib library as a project dependency.
JDK Proxy is a native function of the Java language and does not need to be implemented by loading third-party classes;
Java provides stable support for JDK Proxy and will continue to upgrade and update JDK Proxy. For example, the performance of JDK Proxy in Java 8 is much better than that of previous versions.
JDK Proxy is implemented through interceptor plus reflection;
JDK Proxy can only proxy classes that inherit interfaces;
JDK Proxy is relatively simple to implement and call;
CGLib is a tool provided by a third party, implemented based on ASM, and has relatively high performance;
CGLib does not need to be implemented through interfaces, it completes the call by implementing subclasses.
Static proxy: Static proxies are determined during compilation. You need to write a proxy class for each proxied class. The proxy class and the proxied class implement the same interface or inherit the same parent class.
The proxy class of a static proxy exists at compile time, so it can only proxy specific classes when the program is running, and it is impossible to dynamically decide which classes to proxy.
Static proxies wrap method calls of the original object and can add additional logic before and after the call, but the proxy class needs to be written in advance, which increases the amount of code.
Static proxies explicitly specify proxy objects in the code and are relatively intuitive to use, but adding new proxy classes requires recompilation.
Dynamic Proxy: Dynamic proxy is to create proxy objects at runtime without writing proxy classes in advance. It uses Java's reflection mechanism to dynamically generate proxy classes and proxy objects.
Dynamic proxy is based on interface and is implemented through java.lang.reflect.Proxy class and java.lang.reflect.InvocationHandler interface.
Dynamic proxies can proxy classes of multiple interfaces and dynamically decide which classes to proxy. At runtime, proxies can be generated for different objects as needed, which is more flexible.
Dynamic proxy does not require writing a specific proxy class for each proxied class, which is more flexible and saves code.
Dynamic proxies can add custom logic before and after the proxy object's method call, such as logging, transaction management, etc. The disadvantage of dynamic proxies is that compared to static proxies, generating proxy objects at runtime requires a certain performance overhead.
Static proxy is suitable for the following scenarios:
When the number of target objects (proxied objects) is limited and certain, static proxy can be implemented by manually writing proxy classes. Static proxy creates proxy classes at compile time, so it has better performance at runtime.
Static proxies encapsulate the target object and add additional functionality without modifying the original code. This makes static proxies often used for cross-cutting concerns such as logging and transaction management.
Dynamic proxy is suitable for the following scenarios:
When the number of target objects is uncertain or cannot be determined in advance, dynamic proxy can generate proxy objects more conveniently. It generates proxy classes and proxy objects at runtime, avoiding the tedious work of manually writing multiple proxy classes.
Dynamic proxies can flexibly add, delete, or change proxy behaviors for target objects at runtime, which makes dynamic proxies often used in application scenarios such as AOP (aspect-oriented programming) and RPC (remote procedure call).
It should be noted that since dynamic proxy creates proxy classes and proxy objects through reflection mechanism at runtime, its performance may be slightly lower than that of static proxy. In addition, dynamic proxy can only proxy target objects that implement the interface, while static proxy does not have this limitation.
In summary, static proxy is suitable for scenarios where the number of target objects is limited and certain, and encapsulation and additional functions are required; while dynamic proxy is suitable for scenarios where the number of target objects is uncertain or cannot be determined in advance, and the proxy behavior needs to be flexibly added, deleted, or changed. Choose the appropriate proxy method based on specific needs and situations.
Spring AOP is an important module in the Spring framework, which is used to implement aspect-oriented programming.
Aspect-oriented programmingThis is a programming pattern that allows programmers to modularize through custom crosscutting points, encapsulating behaviors that affect multiple classes into reusable modules. For example, if you don't use AOP, you need to put the log output statements in all classes and methods, but with AOP, you can encapsulate the log output statements into a reusable module, and then put them in the class in a declarative way, and the log output is automatically completed every time the class is used.
In the idea of aspect-oriented programming, the functions are divided into two types
Core Business:Login, register, add, delete, modify, check, all called core business
Peripheral functions:Logs, transaction management, these secondary are peripheral businesses
In aspect-oriented programming, core business functions and peripheral functions are developed independently, and the two are not coupled. Then the aspect functions and core business functions are "woven" together, which is called AOP.
AOP can transform those things that are not related to the business.However, it encapsulates the logic or responsibilities commonly called by business modules (such as transaction processing, log management, permission control, etc.),easy toReduce system duplication of code,Reduce coupling between modules,andFacilitates future scalability and maintainability。
There are several concepts in AOP:
AspectJ: Aspect is just a concept. There is no specific interface or class corresponding to it. It is a general term for Join point, Advice and Pointcut.
Join point: A join point refers to a point in the program execution process, such as a method call, exception handling, etc. In Spring AOP, only method-level join points are supported.
Advice: Advice, that is, the cross-cutting logic in a section we define, has three types: "around", "before" and "after". In many AOP implementation frameworks, Advice is usually used as an interceptor, and can also contain many interceptors as a link around the Join point for processing.
Pointcut: Pointcut, used to match join points. Which Join points in an AspectJ need to be screened by Pointcut.
Introduction: Introduction, allowing an aspect to declare that the advised objects implement any additional interfaces they do not actually implement. For example, a proxy object can proxy two target classes.
Weaving: Weaving, with connection points, pointcuts, notifications, and aspects, how do we apply them to the program? Yes, it is weaving. Under the guidance of pointcuts, the notification logic is inserted into the target method, so that our notification logic can be executed when the method is called.
AOP proxy: AOP proxy refers to the object that implements the aspect protocol in the AOP implementation framework. There are two types of proxies in Spring AOP, namely JDK dynamic proxy and CGLIB dynamic proxy.
Target object: The target object is the object being proxied.
Spring AOP is implemented based on JDK dynamic proxy and Cglib promotion. Both proxy methods are runtime methods, so there is no compile-time processing. Therefore, Spring is implemented through Java code.
Some common behaviors that are scattered across multiple classes or objects (such as logging, transaction management, permission control, interface current limiting, interface idempotence, etc.) are usually called Cross-cutting concerns If we repeat these behaviors in each class or object, it will lead to redundant, complex and difficult to maintain code.
AOP can separate cross-cutting concerns (such as logging, transaction management, permission control, interface current limiting, interface idempotence, etc.) from Core business logic (core concerns) Separate it out to achieve separation of concerns.
Logging: Customize logging annotations and use AOP to implement logging with just one line of code.
Performance statistics: Use AOP to count the execution time of the target method before and after execution, which is convenient for optimization and analysis.
Transaction Management:@Transactional
Annotations allow Spring to perform transaction management for us, such as rolling back exception operations, eliminating the need for repeated transaction management logic.@Transactional
Annotations are implemented based on AOP.
Permission control: Use AOP to determine whether the user has the required permissions before the target method is executed. If so, the target method is executed, otherwise it is not executed. For example, SpringSecurity uses@PreAuthorize
You can customize permission checking by annotating one line of code.
Interface current limiting: Use AOP to limit the current of requests through specific current limiting algorithms and implementations before the target method is executed.
Cache management: Use AOP to read and update the cache before and after the target method is executed.
Common implementation methods of AOP include dynamic proxy, bytecode manipulation, etc.
Spring AOP is based on dynamic proxy. If the object to be proxied implements a certain interface, Spring AOP will use JDK Proxy, to create a proxy object, and for objects that do not implement the interface, you cannot use JDK Proxy to proxy, then Spring AOP will use Cglib Generate a subclass of the proxied object as a proxy
existspring-aop.xml
Configure related beans and aspects in the configuration file
- <?xml version="1.0" encoding="UTF-8"?>
- <beans xmlns="http://www.springframework.org/schema/beans"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
-
- <bean id="target" class="com.xxhh.aopdemo.aop.Target"/>
-
- <bean id="targetAdvice" class="com.xxhh.aopdemo.aop.TargetAdvice"/>
-
- <bean id="targetProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
- <property name="target" ref="target"/> <!--被代理的类-->
- <property name="interceptorNames" value="targetAdvice"/> <!--如果用多种增强方式,value的值使用逗号(,)分割-->
- <property name="proxyTargetClass" value="false"/> <!--如果设置为true,则创建基于类的代理(使用CGLIB);如果设置为false,则创建基于接口的代理(使用JDK动态代理)。-->
- <property name="interfaces" value="com.xxhh.aopdemo.aop.TargetInteface"/> <!--target实现的接口-->
- </bean>
- </beans>
- public interface TargetInteface {
- void method1();
- void method2();
- int method3(Integer i);
- }
- public class Target implements TargetInteface{
-
- /*
- * 需要增强的方法,连接点JoinPoint
- **/
- @Override
- public void method1() {
- System.out.println("method1 running ...");
- }
-
- @Override
- public void method2() {
- System.out.println("method2 running ...");
- }
-
- @Override
- public int method3(Integer i) {
- System.out.println("method3 running ...");
- return i;
- }
- }
- public class TargetAdvice implements MethodInterceptor, MethodBeforeAdvice, AfterReturningAdvice {
-
- /*
- * 通知/增强
- **/
- @Override
- public Object invoke(MethodInvocation methodInvocation) throws Throwable {
- System.out.println("前置环绕通知");
- Object proceed = methodInvocation.proceed();
- System.out.println("后置环绕通知");
- return proceed;
- }
-
- @Override
- public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
- System.out.println("后置返回通知");
- }
-
- @Override
- public void before(Method method, Object[] args, Object target) throws Throwable {
- System.out.println("前置通知");
- }
- }
- public class AopTest {
- public static void main(String[] args) {
- ApplicationContext appCtx = new ClassPathXmlApplicationContext("spring-aop.xml");
- TargetInteface targetProxy = (TargetInteface) appCtx.getBean("targetProxy");
- targetProxy.method1();
- }
- }
Output:
Front surround notification
Pre-notification
method1 running ...
Post-return notification
Rear surround notification
existspring-confaop.xml
Configure related beans and aspects in the configuration file
- <?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: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.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
-
- <!--先开启cglib代理,开启 exposeProxy = true,暴露代理对象-->
- <aop:aspectj-autoproxy proxy-target-class="true" expose-proxy="true"/>
- <!--扫包-->
- <context:component-scan base-package="com.xxhh.aopdemo.annotationaop"/>
-
- </beans>
- /*
- * 目标类
- **/
- public class Target {
-
- public void method1() {
- System.out.println("method1 running ...");
- }
-
- public void method2() {
- System.out.println("method2 running ...");
- }
-
- /*
- * 连接点JoinPoint
- **/
- public int method3(Integer i) {
- System.out.println("method3 running ...");
- // int i1 = 1 / i;
- return i;
- }
- }
- import org.aspectj.lang.ProceedingJoinPoint;
- /*
- * 切面类
- **/
- public class TargetAspect {
-
- /*
- * 前置通知
- **/
- public void before() {
- System.out.println("conf前置通知");
- }
-
- public void after() {
- System.out.println("conf后置通知");
- }
-
- public void afterReturning() {
- System.out.println("conf后置返回通知");
- }
-
- public void afterThrowing(Exception ex) throws Exception {
- // System.out.println("conf异常通知");
- // System.out.println(ex.getMessage());
- }
-
- public Object around(ProceedingJoinPoint pjp) throws Throwable {
- Object proceed = null;
- if (!"".equals("admin")) {
- System.out.println("conf环绕前置");
- proceed = pjp.proceed(pjp.getArgs());
- System.out.println("conf环绕后置");
- }
- return proceed;
- }
- }
- public class AopTest {
- public static void main(String[] args) {
- ApplicationContext appCtx = new ClassPathXmlApplicationContext("spring-confaop.xml");
- Target targetProxy = (Target) appCtx.getBean("target");
- System.out.println(targetProxy.method3(0));
- }
- }
Output:
conf pre-notification
conf surround prepend
method3 running ...
conf post-return notification
conf surround post
conf post notification
0
- <?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: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.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
-
- <!--先开启cglib代理,开启 exposeProxy = true,暴露代理对象-->
- <aop:aspectj-autoproxy proxy-target-class="true" expose-proxy="true"/>
- <!--扫包-->
- <context:component-scan base-package="com.xxhh.aopdemo.annotationaop"/>
-
- </beans>
- @Target(ElementType.METHOD)
- @Retention(RetentionPolicy.RUNTIME)
- @Documented
- public @interface TestAnnotation{
- }
- /*
- * 切面类
- **/
- @Aspect
- @Component
- public class AnnotationAspect {
-
- // 定义一个切点:所有被RequestMapping注解修饰的方法会织入advice
- @Pointcut("@annotation(TestAnnotation)")
- private void advicePointcut() {}
-
- /*
- * 前置通知
- **/
- @Before("advicePointcut()")
- public void before() {
- System.out.println("annotation前置通知");
- }
-
- @After("advicePointcut()")
- public void after() {
- System.out.println("annotation后置通知");
- }
-
- @AfterReturning(pointcut = "advicePointcut()")
- public void afterReturning() {
- System.out.println("annotation后置返回通知");
- }
-
- @AfterThrowing(pointcut = "advicePointcut()", throwing = "ex")
- public void afterThrowing(Exception ex) throws Exception {
- System.out.println("annotation异常通知");
- System.out.println(ex.getMessage());
- }
-
- @Around("advicePointcut()")
- public Object around(ProceedingJoinPoint pjp) throws Throwable {
- Object proceed = null;
- if (!"".equals("admin")) {
- System.out.println("annotation环绕前置");
- proceed = pjp.proceed(pjp.getArgs());
- System.out.println("annotation环绕后置");
- }
- return proceed;
- }
- }
- @Controller
- public class TestController {
-
- @RequestMapping("/test.do")
- @ResponseBody
- public String testController() {
- TestController o = (TestController) AopContext.currentProxy();
- o.test();
- // System.out.println("tewt");
- return "ok";
- }
-
- @TestAnnotation
- public void test() {
- System.out.println("test running");
- }
-
- }