Spring的兩個核心概念html
IOC 方面用Annotation要比用XML更方便java
AOP方面用XML要比用Annotation更強大spring
IOC編程
控制反轉和依賴注入數組
控制反轉(Inversion of Control,英文縮寫爲IoC)是一個重要的面向對象編程的法則來削減計算機程序的耦合問題,也是輕量級的Spring框架的核心。 控制反轉通常分爲兩種類型,依賴注入(Dependency Injection,簡稱DI)和依賴查找(Dependency Lookup)。框架
有一個實體操做接口和實現類ide
public interface UserDAO { public void save(User user); } public class UserDAOImpl implements UserDAO { public void save(User user) { System.out.println("user saved!"); } }
有一個實體類工具
public class User { private String username; private String password; public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } }
有一個工具類post
public class UserService { private UserDAO userDAO; public void add(User user) { userDAO.save(user); } public UserDAO getUserDAO() { return userDAO; } public void setUserDAO(UserDAO userDAO) { this.userDAO = userDAO; } }
由一個測試類測試
public class UserServiceTest { @Test public void testAdd() throws Exception { ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml"); UserService service = (UserService)ctx.getBean("userService"); User u = new User(); u.setUsername("zhangsan"); u.setPassword("zhangsan"); service.add(u); } }
注意這裏紅線的部分,有參數,說明能夠指定xml的位置,同時他還有一個方法是xml數組,就是能夠傳多個xml進去
多個配置文件的好處就是團隊協做,不一樣的人寫不一樣的配置文件,不會衝突
從測試類自己來看,須要兩個地方進行初始化
service對象的初始化,以及add方法中使用的是UserDAO 的哪個實現類是沒有指定的(也就是內部的UserDao沒有初始化)。
可是加入了一個容器:
XML方式的注入
<beans > <bean id="u" class="com.bjsxt.dao.impl.UserDAOImpl"> </bean> <bean id="userService" class="com.bjsxt.service.UserService"> <property name="userDAO" ref="u" /> </bean> </beans>
以後,在spring框架下,這個程序是能夠正常運行的。
也就是說把具體對象的初始化交給這個容器來完成。這個就是控制反轉的意義
控制反轉意思就是說之前能夠在類中控制具體的初始化,如今交給由容器完成
具體的類 從控制實現到控制抽象(接口),從實現具體的東西,到實現抽象的東西
也就是說UserService 類裏面不須要初始化DAO對象
UserServiceTest 類裏面也不須要初始化UserService對象
這些都交給容器來完成
service.add(u) 具體add的具體實現依賴於容器注入給的DAO對象,這個就是依賴注入
1.注入類型
主要有兩種
setter注入就是使用set方法
public class SimpleMovieLister { // the SimpleMovieLister has a dependency on the MovieFinder private MovieFinder movieFinder; // a setter method so that the Spring container can inject a MovieFinder public void setMovieFinder(MovieFinder movieFinder) { this.movieFinder = movieFinder; } // business logic that actually uses the injected MovieFinder is omitted... }
bean.xml不變
構造方法注入用的不多
<bean id="exampleBean" class="examples.ExampleBean"> <constructor-arg type="int" value="7500000"/> <constructor-arg type="java.lang.String" value="42"/> </bean>
2.name和id
<bean name="u" class="com.bjsxt.dao.impl.UserDAOImpl"> </bean>
這兩個基本一致,沒啥區別
3.簡單屬性的注入
對類中通常屬性進行注入,不多用
<bean id="exampleBean" class="examples.ExampleBean"> <constructor-arg name="years" value="7500000"/> <constructor-arg name="ultimateAnswer" value="42"/> </bean>
4.集合注入
5.bean的生存範圍
<bean name="u" class="com.bjsxt.dao.impl.UserDAOImpl" scope="XX"> </bean>
默認是singleton,單例
結果是true
若是類是struct的Action,範圍是prototype
6.bean生命週期
不加的話在用到xml
ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");
這句話的時候就初始化全部的bean
加上的話就是在使用getBean方法的時候初始化
至關的用的少
只有當程序啓動很慢的時候,纔用到
public class UserService { private UserDAO userDAO; public void init() { System.out.println("init"); } public void add(User user) { userDAO.save(user); } public UserDAO getUserDAO() { return userDAO; } public void setUserDAO(UserDAO userDAO) { this.userDAO = userDAO; } public UserService(UserDAO userDAO) { super(); this.userDAO = userDAO; } public void destroy() { System.out.println("destroy"); } }
<bean id="userService" class="com.bjsxt.service.UserService" init-method="init" destroy-method="destroy" scope="prototype"> <constructor-arg> <ref bean="u"/> </constructor-arg> </bean>
init-method destroy-methd 不要和prototype一塊兒用
也是不多用,好比數據源鏈接池的時候用destroy,關閉鏈接池
7.自動裝配 Autowire
<bean name="userDAO" class="com.bjsxt.dao.impl.UserDAOImpl"> <property name="daoId" value="1"></property> </bean> <bean name="userDAO2" class="com.bjsxt.dao.impl.UserDAOImpl"> <property name="daoId" value="2"></property> </bean> <bean id="userService" class="com.bjsxt.service.UserService" scope="prototype" autowire="byName"> </bean>
byName自動裝配/
最後一個bean沒有指定,可是他所在的類裏的屬性是userDAO,它就根據這個name找到了第一個bean
前面都是xml形式的,下面說一下
Annotation的IOC
Annotation的注入
<?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" 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"> <context:annotation-config/>
<bean id="u" class="com.bjsxt.dao.impl.UserDAOImpl"> </bean> <bean id="userService" class="com.bjsxt.service.UserService"> </bean> </beans>
</beans>
使用AutoWire加入注入
autowire會自動到配置文件中去找一個與參數對應類型的bean,注入進來
AutoWire能夠加在任意方法上,只有這個方法須要注入
public class UserService { private UserDAO userDAO; public void add(User user) { userDAO.save(user); } @Autowire public void setUserDAO(UserDAO userDAO) { this.userDAO = userDAO; } }
public class UserServiceTest { @Test public void testAdd() throws Exception { ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml"); UserService service = (UserService)ctx.getBean("userService"); service.add(new User()); } }
能夠看出它注入的方式是byType
可是若是
<bean id="u1" class="com.bjsxt.dao.impl.UserDAOImpl"> </bean> <bean id="u2" class="com.bjsxt.dao.impl.UserDAOImpl"> </bean> <bean id="userService" class="com.bjsxt.service.UserService"> </bean>
這時候就須要Qualifier
public class UserService { private UserDAO userDAO; public void add(User user) { userDAO.save(user); } @Autowire public void setUserDAO(@Qualifier("u1") UserDAO userDAO) { this.userDAO = userDAO; } }
autowire用的很少,下面這種用的比較多
Resouce
它默認的注入方式也是byName,若是name找不到,就byType
想指定名字,直接寫
@Resource(name="u")
@Resource public void setUserDAO(UserDAO userDAO) { this.userDAO = userDAO; }
以上全部的方式在配置文件裏面都要寫待注入的bean
使用
只須要一句,其餘的都不用寫了
<?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" 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"> <context:component-scan base-package="org.example"/>
org.example表示掃描這個包下面的全部類,發現寫有Component的類,而後把他放在容器裏面,造成一個bean。name就是類名首字母小寫,若是想指定名字,就在類上加上@componet("newname"),value就是對象。推薦寫名字
</bean> </beans>
@Test public void testAdd() throws Exception { ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml"); UserService service = (UserService)ctx.getBean("userService"); service.add(new User()); }
那麼它是怎麼注入的呢
在注入類上加入
@Component public class UserDAOImpl implements UserDAO { public void save(User user) { System.out.println("user saved!"); } }
componet 至關因而一個組件,就是把這個類產生的對象當成一個組件,這個組件對於另一個類來講就是一個資源
public class UserService { private UserDAO userDAO; public void add(User user) { userDAO.save(user); } @Resouce public void setUserDAO( UserDAO userDAO) { this.userDAO = userDAO; } }
默認得,spring中 @Component
, @Repository
, @Service
, @Controller
, 這四個註解用法同樣,均可以把類當初一個組件資源
註解裏面還有有Scope,postConstruct,PreDestroy(至關於xml中的init和destory)
AOP
是對面向對象的思惟方式的有力補充
和麪向對象並不矛盾,簡單來講一個是橫着編程,一個是豎着編程
也是兩種實現配置方式
Annotation方式:
<?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-2.5.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd"> <context:annotation-config /> <context:component-scan base-package="com.bjsxt"/> <aop:aspectj-autoproxy /> </beans>
<aop:aspectj-autoproxy /> 的意思是自動產生代理
Aspectj是一個專門產生動態代理,專門面向AOP編程的框架,sprig使用了它
切入點語法:
@Aspect @Component public class LogInterceptor { @Before("execution(public void com.bjsxt.service.UserDAO.add(com.bjsxt.User))")
public void myMethod(){};
}
@Component初始化這個類
@Aspect表示這個是個切面邏輯
@Pointcut("execution(public * com.bjsxt.service..*.add(..))") public void myMethod(){}; }
pointcut鏈接點集合
要加入切面的類必需要由spring管理起來,就是在bean.xml中能找到這個類,也能夠說在類上加@Component
XML方式
這種方式更重要
加入使用別人的切面類,不可能往人家源碼上加Annotation
切面類
public class LogInterceptor { public void myMethod(){}; public void before() { System.out.println("method before"); } public void aroundMethod(ProceedingJoinPoint pjp) throws Throwable { System.out.println("method around start"); pjp.proceed(); System.out.println("method around end"); } }
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" .......>
<context:annotation-config /> <context:component-scan base-package="com.bjsxt"/> <bean id="logInterceptor" class="com.bjsxt.aop.LogInterceptor"></bean> <aop:config> <aop:aspect id="logAspect" ref="logInterceptor"> <aop:before method="before" pointcut="execution(public * com.bjsxt.service..*.add(..))" /> </aop:aspect> </aop:config> </beans>