Spring

 

Spring的兩個核心概念html

  • IOC      (Inversion of Control 控制反轉)
  • AOP     (Aspect Orient Programming 面向切面編程)

 

 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;
    }
}
User

 

有一個工具類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>

 

 

  • bean至關於new一個對象
  • ref至關於引入一個已經new的對象 

 

          以後,在spring框架下,這個程序是能夠正常運行的。

 

          也就是說把具體對象的初始化交給這個容器來完成。這個就是控制反轉的意義

          控制反轉意思就是說之前能夠在類中控制具體的初始化,如今交給由容器完成

          具體的類 從控制實現到控制抽象(接口),從實現具體的東西,到實現抽象的東西

          也就是說UserService 類裏面不須要初始化DAO對象

          UserServiceTest 類裏面也不須要初始化UserService對象

           這些都交給容器來完成

 

          service.add(u)    具體add的具體實現依賴於容器注入給的DAO對象,這個就是依賴注入

 

1.注入類型

 

主要有兩種

  • setter注入
  • 構造方法注入

 

        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生命週期

  • Lazy-initialized beans

不加的話在用到xml

ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");

這句話的時候就初始化全部的bean

加上的話就是在使用getBean方法的時候初始化

 

至關的用的少

只有當程序啓動很慢的時候,纔用到

  • init-method destroy-methd

 

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

使用

     Component 

     只須要一句,其餘的都不用寫了

<?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

 

        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>
相關文章
相關標籤/搜索