Spring
一、SpringIOC
Inversion of controll:控制反转。在web阶段,service层需要使用到dao,那么直接自己来new一个对象出来,进行使用。但是这种方式来创建,耦合度高。第一个优点就是解耦,因为springIOC就是做到了控制反转的作用,不需要自己来new对象,而是配置一下,交给spring框架自己来创建。所以使用spring框架了之后,创建对象就交给了spring框架,我们需要做到的事情就是配置而已。
创建bean有三种方式:
第一种方式:
public class UserDaoImpl {
public void save() {
System.out.println("我是UserDaoImpl中的save方法");
}
}
application.xml中配置:
spring框架创建对象默认是根据类的无参构造方法来进行创建的。
<!-- 配置UserDaoImpl,beandifinationReader读取到了这个之后,就会创建对象 -->
<bean id="userDao" name="userDao1,userDao2" class="com.guang.dao.impl.UserDaoImpl"/>
// 这段配置的意思是:根据这个类的无参构造方法创建对象,这个对象的唯一标识是userDao,别名是userDao1和userDao2
id和name的区别:
id:作为一个bean的唯一标识,这个名字对应容器中唯一的一个对象
name:就相当于是给容器中的对象起了一个别名。如果没有id,name有多个的话,那么以name的第一个值来作为id
class:需要new的是哪个类的对象
scope:这个bean的作用范围。常用的是singleton和prototype,单例和多例对象
init-method:postconstructor,在对象创建之后,进行实例化的方法。执行时间是在容器初始化的时候就已经执行了
destroy-method:在容器关掉的时候,执行的方法。spring框架创建对象之后,就托管给了JVM来管理,scope=prototype的时候,无法执行 这个destroy方法,因为多例对象容器不负责进行销毁
第二种方式:
通过类的静态方法来进行创建
public class StaticFacktory {
// 使用类的静态方法来创建对象
public static UserDao getInstance(){
return new UserDaoImpl();
}
}
application.xml中配置:
<!--用工厂类类的静态方法获取得到对象。静态方法赋值出来的直接就是需要类的实例对象-->
<bean id="userDao" class="com.guang.factory.StaticFacktory" factory-method="getInstance"></bean>
这段配置的意思是说:根据class中的工厂静态方法来创建对象,对象的id是userDao
第三种方式:
通过类的非静态工厂方法创建对象
public class NoStaticFactory {
public UserDao getInstance(){
return new UserDaoImpl();
}
}
application.xml中配置:
<bean id="factorybean" class="com.guang.factory.NoStaticFactory"/>
<bean id="userDao" factory-bean="factorybean" factory-method="getInstance"/>
这段配置的意思是:先利用非静态工厂类来创建一个对象,根据这个对象factorybean的getInstansce方法来创建对象,id为userDao
最常用的就是第一种方式来进行创建。
二、SpringDI
DI:依赖注入。看下面的案例
public class User{
private String name;
private Address address;
}
需要创建一个user对象,那么user对象中有两个属性,需要来给name和address来进行赋值。而name和address的值是需要通过user来进行赋值的。所以这种关系就叫做依赖注入。
在以前的学习过程中,我们可以使用两种方式来进行赋值
public class User{
private String name;
private Address address;
// getter/setter方法来进行赋值
}
public class User{
private String name;
private Address address;
public User(){}
public User(String name,Address address){
this.name=name;
this.adderss=address;
}
}
以前的方式来进行操作的。同样的,spring框架提供了更多的操作方式。但是本质上都是上面的两种方式来进行实现的。
public class UserServiceImpl implements UserService {
// 这里需要使用到userDao的方法,所以这里需要声明下
private UserDao userDao;
public UserDao getUserDao() {
return userDao;
}
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
public void save() {
userDao.save();
System.out.println("我是spring_di中的userserviceImpl中的save方法");
}
}
在application.xml中配置:
<bean id="userDao" class="com.guang.dao.impl.UserDaoImpl"></bean>
<bean id="userService" class="com.guang.service.impl.UserServiceImpl">
<property name="userDao" ref="userDao"/>
</bean>
这段配置意思就是:根据UserDaoImpl类来创建一个对象。根据UserServiceImpl类来创建对象,发现userServiceImpl类中有一个属性userDao,给其进行赋值,那么属性userDao就指向和userDao指向的同一个地址,所以这里完成了属性注入。
还有另外一种给简单类型进行注入的方式
@Value("gaung")
private String name;
三、注解方式
上面中的SpringIOC和SpringDI都可以通过注解方式来记性操作
3.1、给一个类创建一个对象
利用@Controller、@Service、@Reposity和@ComponentScan这四个主要的注解来创建一个对象
前面三个都是最后一个基础上构建起来的。
注解 | 说明 | |
---|---|---|
@Controller | 作用在web包 | |
@Service | 作用在service包下 | |
@Reposity | 作用在dao包下 | |
@ComponentScan | 作用在不是上面三个的包下 |
3.2、给对象进行属性注入
@AutoWired:通过类型进行注入
@Qulifired:通过名字进行注入
@Resource:上面两种的结合。先通过类型注入,如果类型是一样的,那么通过name来进行注入
3.3、java类代替配置文件
在上面的使用过程中,我们每次都需要写配置文件application.xml文件来进行配置。那么spring也提供了这个来进行操作
声明一个主配置类(因为主配置类还可以引用其他的配置文件),在主配置文件中引用其他的配置文件时,其他的配置文件并不需要添加注解@Configration。如下所示:
@Configration // 声明这个类为主配置类
@Import(MyConfig.class) // 引用其他的配置类,但是其他的配置类可以不加@Configration注解
public class Config{
}
// 另外一个配置文件
public class MyConfig{
}
因为使用了注解,所以以前在配置文件中手动添加类来创建对象也可以进行省略,使用配置文件来进行创建bean对象。
直接添加类上添加注解/在配置类中创建对象
@Service("userService") // 这个类对象的id是userService
public class UserServiceImpl implements UserService{
@Autowired
@Qulifired("userDao")
private UserDao userDao;
@Value("${jdbc.username}")
private String username;
@Bean("user") // 如果不设置这里名字,那么方法名称将会是这个对象的id
public UserDao getInstance(){
return new User();
}
// 这里非常类似springMVC中@RequestParam(value="dataSource") DataSource datasource
// 表示的是如果这两个名字不一样,那么形成一种映射关系,将dataSource和datasource进行绑定,也就是将dataSource的值赋值给
// datasource。和springmvc的手法如出一辙
@Bean(value = "queryRunner")
public QueryRunner queryRunner(@Qualifier("dataSource") DataSource dataSource){
QueryRunner queryRunner = new QueryRunner(dataSource);
return queryRunner;
}
}
给出一个例子来进行进行演示:
在resouces下创建db.properties
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/spring
jdbc.username=root
jdbc.password=root
使用类来代替配置文件
@ComponentScan(value = "com.guang") // 扫描这个包下的所有的注解,是否有几个常用的声明是bean的注解。
@PropertySource(value = "classpath:db.properties") // 加载配置文件,从配置文件中获取得到信息
@Configuration // 声明这个类为一个主配置类
public class Config {
// 获取得到db.properties中所有的信息
// 得到的是do.properties中的jdbc.drier的信息
@Value(value = "${jdbc.driver}")
private String driver;
@Value(value = "${jdbc.url}")
private String url;
@Value(value = "${jdbc.username}")
private String username;
@Value(value = "${jdbc.password}")
private String password;
// 获取得到数据库连接池
@Bean("dataSource")
public DataSource getDataSource() throws PropertyVetoException {
// 获取得到c3p0的数据源
ComboPooledDataSource dataSource = new ComboPooledDataSource();
dataSource.setDriverClass(driver);
dataSource.setJdbcUrl(url);
dataSource.setUser(username);
dataSource.setPassword(password);
return dataSource;
}
// 使用queryRunner来获取得到对象
@Bean(value = "queryRunner")
public QueryRunner queryRunner(@Qualifier("dataSource") DataSource datasource){
QueryRunner queryRunner = new QueryRunner(datasource);
return queryRunner;
}
}