一.Spring代理的特點
? ? ? ? ?1.依賴注入和初始化影響的是原始的對象。
? ? ? ? ?2.代理和目標是兩個對象,二者成員變量不共用數據。
二.測試
首先準備以下幾個類。
Bean1
package com.example.springdemo.demos.a13;import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;import javax.annotation.PostConstruct;/*** @author zhou* @version 1.0* @description TODO* @date 2025/8/30 20:33*/
@Component
public class Bean1 {private static final Logger log = LoggerFactory.getLogger(Bean1.class);protected Bean2 bean2;protected boolean initialized;@Autowiredpublic void setBean2(Bean2 bean2){log.debug("setBean");this.bean2 = bean2;}@PostConstructpublic void init(){log.debug("init");initialized = true;}public Bean2 getBean2(){log.debug("getBean2()");return bean2;}public boolean isInitilized(){log.debug("isInitilized()");return this.initialized;}}
? ? ?Bean2
package com.example.springdemo.demos.a13;import org.springframework.stereotype.Component;/*** @author zhou* @version 1.0* @description TODO* @date 2025/8/30 20:36*/
@Component
public class Bean2 {
}
切面類
package com.example.springdemo.demos.a13;import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.stereotype.Component;/*** @author zhou* @version 1.0* @description TODO* @date 2025/8/30 20:32*/
@Aspect
@Component
public class MyAspect {//對所有方法增強@Before("execution(* com.example.springdemo.demos.a13.Bean1.*(..))")public void before(){System.out.println("before");}}
TestProxy(測試代理類)
package com.example.springdemo.demos.a13;import org.springframework.aop.framework.Advised;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;/*** @author zhou* @version 1.0* @description TODO* @date 2025/8/30 20:41*/
@SpringBootApplication
public class TestProxy {public static void main(String[] args) throws Exception {ConfigurableApplicationContext context = SpringApplication.run(TestProxy.class, args);Bean1 proxy = context.getBean(Bean1.class);proxy.setBean2(new Bean2());proxy.init();context.close();showProxyAndTarget(proxy);System.out.println(">>>>>>>>>>>>>");System.out.println(proxy.getBean2());System.out.println(proxy.isInitilized());}public static void showProxyAndTarget(Bean1 proxy) throws Exception{System.out.println(">>>>>>>>代理中的成員變量");System.out.println("initialized="+proxy.initialized);System.out.println("bean2="+proxy.bean2);if(proxy instanceof Advised){System.out.println(">>>>>>>>>>>目標中的成員變量");//獲取目標對象Bean1 target = (Bean1) ((Advised) proxy).getTargetSource().getTarget();System.out.println(target);System.out.println("\tinitialized==="+target.initialized);System.out.println("\tbean2="+target.bean2);}}
}
測試結果:
? ? ? ?目標對象進行了初始化操作。
? ? ? ?代理對象中的成員變量沒有被賦值,而目標對象是有值的。并且我們通過代理對象調用方法也可以得到成員變量的值,最后打印bean2對象以及initialized的值。這是因為代理對象調用方法最后走的還是目標對象的方法,所以這兩個屬性有值。
三.遇到的問題
? ? ? ? ?在測試過程中,控制臺并沒有打印日志。原因是這是一個新建的案例項目,我們還得配置logback-spring.xml文件,控制日志的輸出規則。文件存方在Resources目錄下。
<?xml version="1.0" encoding="UTF-8"?>
<configuration><!-- 控制臺輸出 --><appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender"><encoder><pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern></encoder></appender><!-- 設置日志級別 --><root level="DEBUG"><appender-ref ref="CONSOLE" /></root><!-- 針對特定包設置日志級別 --><logger name="com.example.springdemo.demos.a13" level="DEBUG" />
</configuration>