傳統模式:調用者主動 new 被調用者。Spring 模式:容器負責創建被調用者並注入調用者,實現「控制反轉」。兩種注入方式:Setter 注入(直觀自然)與建構子注入(可控制依賴順序)。
public class Happy {
private String happyInfo;
public void happy() { System.out.println(happyInfo); }
// getter/setter...
}
<bean id="happy" class="cn.wgy.day_01.entity.Happy">
<property name="happyInfo" value="中秋快樂"/>
</bean>
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
Happy happy = (Happy) ctx.getBean("happy");
happy.happy();
| 特性 | BeanFactory | ApplicationContext |
|---|---|---|
| 國際化 | 不支援 | 支援 (MessageSource) |
| 事件機制 | 無 | 完整事件發布/監聽 |
| 資源載入 | 無 | 實現 ResourceLoader |
| Web 支援 | 程式化建立 | 聲明式 + ContextLoaderListener |
| Bean 載入 | 延遲載入 | 啟動時一次性載入(早發現錯誤) |
| 後處理器註冊 | 手動 | 自動 |
生產環境建議使用 ApplicationContext。
<bean id="user1" class="cn.wgy.day01.entity.User">
<constructor-arg index="0" type="java.lang.String" value="Promise"/>
<constructor-arg index="1" type="java.lang.String" value="Promise@163.com"/>
</bean>
<!-- p 命名空間 -->
<beans xmlns:p="https://www.springframework.org/schema/p" ...>
<bean id="user" class="..." p:username="Promise" p:dao-ref="dao"/>
</beans>
<property name="names"><list><value>A</value><value>B</value></list></property> <property name="address"><set><value>北京</value></set></property> <property name="map"><map><entry key="k"><value>v</value></entry></map></property> <property name="hobbies"><props><prop key="f">足球</prop></props></property> <property name="email"><value></value></property> <!-- 空串 --> <property name="email"><null/></property> <!-- null -->
public class LoggerBefore implements MethodBeforeAdvice { ... }
public class LoggerAfter implements AfterReturningAdvice { ... }
public class AroundLog implements MethodInterceptor { ... }
public class ErrorLog implements ThrowsAdvice { ... }
<bean id="biz" class="...UserBiz"><property name="dao" ref="dao"/></bean>
<bean id="loggerBefore" class="...LoggerBefore"/>
<bean id="loggerAfter" class="...LoggerAfter"/>
<bean id="serviceProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="targetName" value="biz"/>
<property name="interceptorNames" value="loggerBefore,loggerAfter"/>
</bean>
<bean id="advisor" class="org.springframework.aop.support.NameMatchMethodPointcutAdvisor">
<property name="advice" ref="around"/>
<property name="mappedNames" value="delete"/>
</bean>
<bean id="regex" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
<property name="advice" ref="around"/>
<property name="pattern" value=".*do.*"/>
</bean>
Proxy.newProxyInstance(classLoader, interfaces, invocationHandler)。InvocationHandler.invoke(proxy, method, args) 中攔截、增強、反射調用目標方法。Enhancer.setSuperclass(clazz).setCallback(methodInterceptor).create()。final 方法/類。<aop:aspectj-autoproxy proxy-target-class="true"/> → CGLIB。
