javascript
Spring_Bean配置_生命周期_注解
Spring
Spring是一個開源框架,Spring是于2003 年興起的一個輕量級的Java 開發框架,由Rod Johnson 在其著作Expert One-On-One J2EE Development and Design中闡述的部分理念和原型衍生而來。它是為了解決企業應用開發的復雜性而創建的。框架的主要優勢之一就是其分層架構,分層架構允許使用者選擇使用哪一個組件,同時為 J2EE 應用程序開發提供集成的框架。Spring使用基本的JavaBean來完成以前只可能由EJB完成的事情。然而,Spring的用途不僅限于服務器端的開發。從簡單性、可測試性和松耦合的角度而言,任何Java應用都可以從Spring中受益。Spring的核心是控制反轉(IoC)和面向切面(AOP)。簡單來說,Spring是一個分層的JavaSE/EE full-stack(一站式) 輕量級開源框架。
Spring核心
1.控制反轉(IOC)
2.面向切面(AOP)
Spring優點
1.解耦, 簡化開發: Spring就是一個工廠,可以將所有對象創建和依賴關系維護交給Spring處理
2.AOP支持: 方便實現事務處理, 權限處理, 監控操作
3.聲明式事務支持: 只需通過配置就可以完成事務管理
4.提供Junit支持
5.集成其他框架
6.對JavaEE API的封裝, 降低開發難度
Spring體系結構
Spring是一個分層架構, 包含的功能可分為大約20個模塊.
Core Container(核心容器):Beans: 管理BeansCore: Spring核心Context: 配置文件ExpressionLanguage: SpEL表達式 AOP(切面編程) AOP框架: Aspects Data Access(數據庫整合):JDBC, ORM, OXM, JMS, Transaction Web(MVC Web開發):Web, Servlet, Portlet, Struts Test(Junit整合)IOC(控制反轉)
IOC(控制反轉): 將創建對象實例交給Spring處理, 每次從Spring工廠中獲得對象
下面使用一個簡單的例子說明:
目標類:
public interface UserService{void addUser(); } public class UserServiceImpl implements UserService {public void addUser() {System.out.println("ico add user");} }Spring的配置文件:
配置文件名, 放置的位置都是任意的, 一般將配置文件命名為applicationContext.xml, 放置在src下
測試代碼:
public class TestIoc {@Testpublic void f1(){//XMLPATH代表配置文件所在的位置String XMLPATH="applicationContext.xml";//使用ClassPathXMLApplicationContext(String path)加載指定位置的配置文件ApplicationContext applicationContext = new ClassPathXmlApplicationContext(XMLPATH);//使用applicationContext的getBean獲得配置文件中id為userService的對象UserService userService = (UserService) applicationContext.getBean("userService");userService.addUser();} }測試方法中不再使用new的方式獲得對象, 而是通過控制反轉, 將new的行為交給Spring處理(反射機制)
DI(依賴注入)
DI依賴注入: 對實例對象的屬性賦值, 一般通過set方法進行反射賦值.
對象的屬性一般指另一個對象(就有依賴一說)
下面使用例子說明DI
User的Service層:
public interface UserService{void addUser(); }public class UserServiceImpl implements UserService {//對UserDao對象做依賴注入, 在后面生成get/set方法private UserDao userDao;public void addUser() {userDao.save();}public UserDao getUserDao() {return userDao;}public void setUserDao(UserDao userDao) {this.userDao = userDao;} }User的Dao層:
public interface UserDao {void save(); }public class UserDaoImpl implements UserDao {public void save() {System.out.println("di save");} }applicationContext.xml:
<?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"><!--property標簽用于依賴注入:將ref映射的對象注入到name中name:需要注入的屬性名ref:映射到UserDao對象 --><bean id="userService" class="com.b_di.UserServiceImpl"><property name="userDao" ref="userDao"></property></bean><bean id="userDao" class="com.b_di.UserDaoImpl"></bean> </beans>測試:
測試中代碼與前面一樣幾乎不變, 對象的生成, 對象屬性的賦值都交給Spring處理, 高度解耦
Spring核心API
頂級接口: BeanFactory用于生成任意的Bean, 采取延遲加載策略, 使用getBean才會初始化BeanBeanFactory子接口: ApplicationContext功能加強, 使用該接口, 當配置文件被加載的時候, 就進行對象實例化ApplicationContext子接口:1.ClassPathXmlApplicationContext用于加載src下的xml運行時, xml在/WEB-INF/classes/...xml2.FileSystemXmlApplicationContext加載指定盤符下的xml運行時, xml在/WEB-INF/...xml舉例說明BeanFactory
public class TestBeanFactory {@Testpublic void f1(){String XMLPATH="applicationContext.xml";//加載完配置文件后, 并不會實例化BeanFactory applicationContext = new XmlBeanFactory(new ClassPathResource(XMLPATH));UserService userService = (UserService) applicationContext.getBean("userService");userService.addUser();} }調用ClassPathXmlApplicationContext(XMLPATH)加載配置文件, Spring就會調用配置文件中的配置的bean的構造函數, 而XMLBeanFactory(Resource)不會, 只是單純加載配置文件, 只有當getBean才會調用構造函數
基于XML裝配Bean
3種Bean實例化方式:
默認構造獲得Bean, 使用靜態工廠獲得Bean, 使用實例工廠獲得Bean
- 使用默認構造函數:
- 靜態工廠:
- 實例工廠:
先獲得工廠的實例對象, 然后通過實例對象創建想要的對象, 實例工廠提供的方法都是非靜態方法
Spring中Bean種類
普通Bean: Spring直接創建實例<bean id="普通Bean名" class="普通Bean"></bean>FactoryBean: 生產特定Bean的工廠,可以是靜態/非靜態工廠 非靜態舉例<bean id="工廠對象名" class="工廠類"></bean><bean id="特定Bean" factory-bean="工廠對象名" factory-method="工廠方法名">BeanFactory: 使用動態代理生成任意的BeanBean作用域
確定Spring創建Bean實例個數, 在bean標簽中使用scope屬性確定
singleton(默認值):在Spring中只存在一個Bean實例, 單例模式. prototype:getBean()的時候都會new Bean(), 多例 request:每次http請求都會創建一個Bean, 僅用于WebApplicationContext環境 session:同一個http session共享一個Bean, 不同Session使用不同的Bean, 使用環境同上 globalSession:用于Portlet, 環境同上<bean id="..." class="..." scope="..."></bean>Spring生命周期
生命周期詳情:
1.instantiate bean對象實例化 2.populate properties 封裝屬性 3.如果Bean實現BeanNameAware 執行 setBeanName 4.如果Bean實現BeanFactoryAware 或者 ApplicationContextAware 設置工廠 setBeanFactory 或者上下文對象 setApplicationContext 5.如果存在類實現 BeanPostProcessor(后處理Bean) ,執行postProcessBeforeInitialization 6.如果Bean實現InitializingBean 執行 afterPropertiesSet 7.調用<bean init-method="init"> 指定初始化方法 init 8.如果存在類實現 BeanPostProcessor(處理Bean) ,執行postProcessAfterInitialization 9.執行業務處理 10.如果Bean實現 DisposableBean 執行 destroy 11.調用<bean destroy-method="customerDestroy"> 指定銷毀方法 customerDestroy- 初始化與銷毀
在構造方法前->初始化, 容器關閉時->銷毀
下面使用一個簡單例子演示:
applicationContext.xml:<bean id="userService" class="com.e_lifeCycle.UserServiceImpl" init-method="myInit" destroy-method="myDestory"></bean>UserServiceImp.java: public class UserServiceImpl implements UserService {public void addUser() {System.out.println("lifeCycle add User");}public void myInit() {System.out.println("init");}public void myDestory() {System.out.println("destory");} }Test:@Testpublic void f1(){String XMLPATH="com/e_lifeCycle/applicationContext.xml";ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext(XMLPATH);UserService userService = (UserService) applicationContext.getBean("userService");userService.addUser();//ApplicationContext沒有close方法, 使用ClassPathXmlApplicationapplicationContext.close();} //在執行構造完Bean對象的時候執行myInit //在容器關閉之前執行myDestory- BeanPostProcessor實現AOP, 完成事務處理
Bean實現BeanPostProcessor, 當Spring管理Bean的時候,
就能在初始化方法前執行PostProcessAfterInitialization(Object bean, String beanName);
在初始化方法后執行PostProcessBeforeInitialization(Object bean, String beanName);
下面舉例說明:
編寫BeanPostProcessor: public class PostProcessor implements BeanPostProcessor{/*** 執行方法之前調用, 就意味著在初始化的時候就會調用事務處理* 此時的事務處理是針對接口中有的方法*/@Overridepublic Object postProcessBeforeInitialization(final Object bean, String beanName)throws BeansException {System.out.println("方法前"+beanName);return bean;}@Overridepublic Object postProcessAfterInitialization(final Object bean, String beanName)throws BeansException {System.out.println("方法后"+beanName);return Proxy.newProxyInstance(PostProcessor.class.getClassLoader(), bean.getClass().getInterfaces(), new InvocationHandler() {//反射重寫invoke, 實現AOP@Overridepublic Object invoke(Object proxy, Method method, Object[] args)throws Throwable {System.out.println("開啟事務");Object objectInvoke = method.invoke(bean, args);System.out.println("關閉事務");return objectInvoke;}});} }在applicationContext.xml中配置: <bean class="com.e_lifeCycle.PostProcessor"></bean> 注冊自定義的BeanPostProcessor測試類: 測試類就是前面的初始化與銷毀代碼 運行結果:構造方法前userServiceinit方法后userService開啟事務lifeCycle add User關閉事務destory生命周期, 事件執行流程
使用上面的lifeCycle作為例子
1.加載配置文件, 構造方法執行 2 裝載屬性,調用setter方法 3.通過BeanNameAware接口,獲得配置文件id屬性的內容:lifeUser 4.通過ApplicationContextAware接口,獲得Spring容器 5. 實現BeanPostProcessor后處理,初始化前,執行postProcessBeforeInitialization方法 6.通過InitializingBean,確定屬性設置完成之后執行 7.配置init-method執行自定義初始化方法 8. 實現BeanPostProcessor后處理,在自定義初始化之后,執行postProcessAfterInitialization方法 9.通過DisposableBean接口,不需要配置的銷毀方法 10.配置destroy-method執行自定義銷毀方法屬性依賴注入
1.通過構造方法進行裝配:
在bean標簽中添加constructor-arg標簽進行裝配.
例如:
注: 使用這個參數每次都是調用Bean中首次與標簽中數據匹配合適構造函數
2.使用setter方法注入:
就是使用property標簽指定name, value/ref值
P命名空間
主要對"setter方法依賴注入"做簡化, 替換property.
在添加P命名空間:
在beans標簽中添加: xmlns:p=“http://www.springframework.org/shema/p”
SPEL
用于簡化property中屬性名, 與屬性值的寫法, 類似于EL表達式
例:
<property name="cname" value="#{'jack'}"></property> <property name="cname" value="#{customerId.cname.toUpperCase()}"></property>通過另一個bean,獲得屬性,調用的方法 <property name="cname" value="#{customerId.cname?.toUpperCase()}"></property> ?. 代表: 如果對象不為null,將調用方法4.集合注入:
在property標簽中注入集合數據
基于注解裝配Bean
使用注解的前提:
在 beans 標簽下添加 context:component-scan標簽, 掃描包下所有類的注解 <context:component-scan base-package="com.itheima.g_annotation.a_ioc"></context:component-scan>取代 bean 標簽的注解:
1. @Component("beanId")等價于<bean id="beanId" class="...">@Component("userServiceId")public Class UserServiceImpl implements UserService{//.............. }2. 在web中, 提供3個注解用于標識三層架構, 這3個注解效果與Component一樣@Repository: dao層@Service: service層@Controller: web層取代setter依賴注入的注解:
在類中對象的屬性上加注解, 就能完成注入(沒有setter方法也可以注入)
上面有錯, 還請指出, 如果認為我寫的還不錯, 還請點個贊, 多多支持一下, O(∩_∩)O~~
總結
以上是生活随笔為你收集整理的Spring_Bean配置_生命周期_注解的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python 爬虫是什么_“python
- 下一篇: gradle idea java ssm