一、IOC和DI的理解
1、两个词:控制、反转
类的实现的控制权从调用类中移除并转交个容器(Spring)
2、DI更好的阐述了以上概念
类的实现依赖容器注入更加清晰
3、DI的类型
构造函数的注入、属性注入(setter注入)、接口注入
interface Service {
public void injectUserDao(UserDao userDao);
}
class UserService implements Service {
private UserDao userDao;
//构造函数的注入
public UserService(UserDao userDao) {
this.userDao = userDao;
}
// 属性的注入
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
//接口注入
@Override
public void injectUserDao(UserDao userDao) {
this.userDao = userDao;
}
}
4、容器的注入
<?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">
<bean id="userDAO" class="com.sosop.dao.imp.UserDAOImp" />
<bean id="userService" class="com.service.imp.UserServiceImp"
p: userDAO-ref="userDAO"/>
</beans>
实现原理:使用java的反射机制
由ClassLoader的loadClass("com.sosop....")加载字节码Class对象,再由Class对象newInstance生成实例以及获得类的构造方法、字段以及方法等成员,具体参考java的反射
5、资源抽象接口
Resource接口有很多实现类,如ClassPathResource,FileSystemResource等
资源地址的表达式:
类路径加载资源:classpath: com/sosop/...
目录中加载资源:file:/home/sosop/...
WEB服务器中加载资源:http://www.sososp.com/...
ftp服务器中加载资源:ftp://www.sosop.com/...
ApplicationContext对应的类: com/sososp/bean.xml
二、IoC容器装配bean
1、装配一个bean
<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">
<bean id="idName" class="package.class">
</bean>
2、bean命名:尽量使用id,避免使用name
区别就是name上命名几乎没有任何限制,使用id吧
3、依赖注入
<?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:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- 属性注入 -->
<bean id="user1" class="com.sosop.model.User">
<property name="name"><value>sosop</value></property>
</bean>
<bean id="user2" class="com.sosop.model.User">
<property name="name" value="sosop"/>
</bean>
<bean id="friend" class="com.sosop.model.User"/>
<bean id="user3" class="com.sosop.model.User">
<property name="friend" ref="friend"/>
</bean>
<!-- 构造器注入 -->
<bean id="user4" class="com.sosop.model.User">
<!-- 这里还有根据类型type、根据index参数的顺序 -->
<constructor-arg name="name" value="sosop"/>
</bean>
<!-- 非静态工厂类 -->
<bean id="factory" class="com.sosop.UserFactory"/>
<bean id="user5" factory-bean="factory" factory-method="createUser"/>
<!-- 静态工厂类 -->
<bean id="user6" class="com.sosop.StaticUserFactory" factory-method="getInstance"/>
<bean/>
<!-- null -->
<bean id="user7" class="com.sosop.model.User">
<property name="name"><null/></property>
</bean>
<!--级联 -->
<bean id="user8" class="com.sosop.model.User">
<property name="friend.name"><value>oudi</value></property>
</bean>
<!-- 集合 -->
<bean id="user9" class="com.sosop.model.User">
<!-- List -->
<property name="books">
<list>
<value>java</value>
<value>c</value>
<value>ruby</value>
</list>
</property>
<!-- Set -->
<property name="hobies">
<list>
<value>football</value>
<value>swimming</value>
<value>girls</value>
</list>
</property>
<!-- Map -->
<property name="phone">
<map>
<entry key="telephone" value="1234567"/>
<entry key="mobilphone" value="18888888888"/>
</map>
</property>
<!-- Porperties -->
<property name="mails">
<props>
<prop key="sian">[email protected]</prop>
<prop key="gmail">[email protected]</prop>
</props>
</property>
</bean>
<!--
记住集合合并:父集合有abstract,子集合parent,集合属性merge=true
方便快捷的配置集合类型使用util命名空间
-->
<!--
使用P命名空间:xmlns:p="http://www.springframework.org/schema/p"
-->
<bean id="user10" class="com.sosop.model.User" p:name="sosop" p:friend-ref="friend" />
</beans>
5、自动装配
byName、byType、constructor、autodetect(有默认构造则用byType,否则用constructor)
6、类之间的关系
继承:父类abstract=true 子类parent="父类id"
依赖:depends-on="classId"
引用:p: id="classId" <idref bean="classId"/>
7、整合多个配置文件
在applicationContext.xml中整合多个配置文件,当多个人开发一个项目,每个人负责一个模块或功能时,很有用
<import resource="classpath*: com/sosop/*" />
<import resource="services.xml"/>
<import resource="resources/messageSource.xml"/>
<import resource="/resources/themeSource.xml"/>
8、bean的作用域:singleton、prototype、request、session、globalSession
三、基于注解配置
现在在项目中一般都使用注解的方式,方便简洁
下面是不久前做的一个项目部分注解配置
<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" xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:p="http://www.springframework.org/schema/p" xmlns:tx="http://www.springframework.org/schema/tx"
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
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd">
<aop:aspectj-autoproxy proxy-target-class="true"/>
<context:annotation-config />
<context:component-scan base-package="com.tcl.phone" />
<context:property-placeholder location="classpath:jdbc.properties" />
<tx:annotation-driven transaction-manager="transactionManager"
proxy-target-class="true"/>
<mvc:annotation-driven />
<bean
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"
p:locations="classpath:jdbc.properties" p:fileEncoding="utf-8" />
<bean id="dataSource" destroy-method="close"
class="org.apache.commons.dbcp.BasicDataSource" p:driverClassName="${jdbc.drive}"
p:url="${jdbc.url}" p:username="${jdbc.username}" p:password="${jdbc.password}"
p:maxActive="${jdbc.maxActive}" p:maxIdle="${jdbc.maxIdle}" p:maxWait="${jdbc.maxWait}"
p:defaultAutoCommit="${jdbc.defaultAutoCommit}" />
<bean id="txManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager"
p:dataSource-ref="dataSource" />
<tx:advice id="txAdvice" transaction-manager="txManager">
<tx:attributes>
<tx:method name="find*" read-only="true" />
<tx:method name="*" />
</tx:attributes>
</tx:advice>
<aop:config>
<aop:pointcut id="serviceOperation"
expression="execution(* com.tcl.phone.service..*.*(..))" />
<aop:advisor advice-ref="txAdvice" pointcut-ref="serviceOperation" />
</aop:config>
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"
p:dataSource-ref="dataSource"
p:configLocation="classpath:com/tcl/phone/data/mybatis-config.xml"
p:mapperLocations="classpath*:com/tcl/phone/data/*Mapper.xml" />
<bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
<constructor-arg index="0" ref="sqlSessionFactory"/>
</bean>
</beans>
package com.tcl.phone.model;
import org.springframework.stereotype.Component;
@Component
public class Admin {
private int id;
private String name;
public Admin() {}
public Admin(int id) {
super();
this.id = id;
}
public Admin(String name) {
super();
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
package com.tcl.phone.dao.imp;
import org.springframework.stereotype.Repository;
import com.tcl.phone.dao.IAdminDAO;
import com.tcl.phone.model.Admin;
@Repository("adminDAO")
public class AdminDAO extends BaseDAO<Admin> implements IAdminDAO {
}
package com.tcl.phone.service.imp;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import javax.annotation.Resource;
import org.springframework.stereotype.Service;
import com.tcl.phone.dao.IAdminDAO;
import com.tcl.phone.model.Admin;
import com.tcl.phone.service.IAdminService;
@Service("adminService")
public class AdminService implements IAdminService {
private IAdminDAO adminDAO;
@Resource(name="adminDAO")
public void setUserDao(IAdminDAO adminDAO) {
this.adminDAO = adminDAO;
}
@Override
public boolean validAdmin(String name) {
Map<String, Object> map = new HashMap<>();
map.put("a_name", name.trim());
Admin admin = adminDAO.selectByFields(map);
if(admin == null)
return false;
else
return true;
}
@Override
public String save(Admin admin) {
//admin.setName(admin.getName().trim().replace(" ", "."));
return String.valueOf(adminDAO.insert(admin));
}
@Override
public String remove(String name) {
Map<String, Object> map = new HashMap<>();
map.put("a_name", name);
return String.valueOf(adminDAO.deleteByField(map));
}
@Override
public Set<String> query() {
Set<String> admins = new HashSet<>();
for(Admin admin : adminDAO.select(new Admin())) {
admins.add(admin.getName());
}
return admins;
}
}
package com.tcl.phone.web.controller;
import java.util.Map;
import java.util.Set;
import javax.annotation.Resource;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;
import com.tcl.phone.model.Admin;
import com.tcl.phone.service.IAdminService;
import com.tcl.phone.utils.CollectionUtil;
import com.tcl.phone.utils.Constant;
import com.tcl.phone.utils.LDAPUtil;
@Controller
public class AdminController {
private IAdminService adminService;
@Resource(name="adminService")
public void setAdminService(IAdminService adminService) {
this.adminService = adminService;
}
@RequestMapping(Constant.ADMIN_ADD_PATH)
public @ResponseBody String addAdmin(@RequestParam String name) {
String real = name.trim();
return adminService.save(new Admin(real));
}
@RequestMapping(Constant.ADMIN_REMOVE_PATH)
public @ResponseBody String removeAdmin(@RequestParam String name) {
return adminService.remove(name.trim());
}
@RequestMapping(Constant.ADMIN_SHOW_PATH)
public ModelAndView showAdmin() {
ModelAndView mav = new ModelAndView();
Set<String> admins = adminService.query();
Map<String, String> users = LDAPUtil.getUsers();
mav.addObject("admins", admins);
//mav.addObject("users", new CollectionUtil<String>().sub(users, admins));
mav.addObject("users", new CollectionUtil<String, String>().removeKeys(users, admins));
mav.addObject("menu", 11);
mav.setViewName(Constant.ADMIN_PAGE_PATH);
return mav;
}
}
<context:component-scan base-package="org.example">
<context:include-filter type="regex" expression=".*Stub.*Repository"/>
<context:exclude-filter type="annotation"
expression="org.springframework.stereotype.Repository"/>
</context:component-scan>
@Autowire和@Qualifier很少用