bean的别名配置:
在bean内,还有一个属性叫name,可以为bean起别名,里面的别名可以是多个,可以用空格、逗号、分号分开,如下:
<bean id="bookDao" name="bookDao2 bookDao3,bookDao4;bookDao5" class="dao.impl.BookDaoImpl"/>
起别名后,getBean("")方法和ref里面都可以用别名。
bean的单例模式修改:
在bean内,还有一个属性叫scope,其参数列表有两个,一个是"singleton",表示单例模式,一个是"prototype",表示多例模式。bean默认下为单例模式,因为其本身存在的意义就是存放和管理可以复用的对象。
测试单例和多例:
public class App2 {
public static void main(String[] args) {
// 获取IoC容器,参数是自己配置的applicationContext.xml文件
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
// 通过getBean方法获取bean,参数是在bean中设置的id名字
BookService bookService1 = (BookService) ac.getBean("service2");
System.out.println(bookService1);;
BookService bookService2 = (BookService) ac.getBean("service2");
System.out.println(bookService2);
}
}
左多例,右单例。
实例化bean:
通过构造方法:
<bean id="bookDao" name="Dao" class="dao.impl.BookDaoImpl"/>
通过静态工厂(了解即可):
<bean id="orderDao" class="factory.OrderDaoFactory" factory-method="getOrderDao"/>
通过实例工厂(了解即可):
<bean id="orderDaoFactory" class="factory.OrderDaoFactory"/>
<bean id="orderDao" factory-method="getOrderDao" factory-bean="orderDaoFactory"/>
通过工厂bean(重要,是实例工厂的进阶):
package factory;
import org.springframework.beans.factory.FactoryBean;
import service.BookService;
import service.Impl.BookServiceImpl;
public class BookServiceFactoryBean implements FactoryBean<BookService> {
@Override
public BookService getObject() throws Exception {
return new BookServiceImpl();//代替原始实例工厂中创建对象的方法
}
@Override
public Class<?> getObjectType() {
return BookService.class;//返回什么类型,即这个工厂要创建什么类型的对象
}
@Override
public boolean isSingleton() {
return true;//单例模式为true 非单例模式为false,默认为单例模式
}
}
<bean id="bookService" class="factory.BookServiceFactoryBean"></bean>
注意:不适用于BookServer这种和其他类对象有关联,需要依赖注入的,会报错NullPointerException。
bean的生命周期:
package dao.impl;
import dao.BookDao;
public class BookDaoImpl implements BookDao {
public void save()
{
System.out.println("book dao save...");
}
public void init()
{
System.out.println("book dao init...");
}
public void destroy()
{
System.out.println("book dao destroy...");
}
}
<bean id="bookDao" class="dao.impl.BookDaoImpl" init-method="init" destroy-method="destroy"/>
运行后发现,没有book dao destroy,即没有执行析构函数。
要想让bean析构,我们需要把ApplicationContext换成其子类ClassPathXmlApplicationContext才能调用后者的特有方法close。
import dao.BookDao;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class App2 {
public static void main(String[] args) {
ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext
("applicationContext.xml");
BookDao bookDao =(BookDao) ac.getBean("bookDao");
bookDao.save();
ac.close();
}
}
或者是注册关闭钩子,其可以放在任何地方,最后一行也可以。
import dao.BookDao;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class App2 {
public static void main(String[] args) {
ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext
("applicationContext.xml");
ac.registerShutdownHook();
BookDao bookDao =(BookDao) ac.getBean("bookDao");
bookDao.save();
ac.close();
}
}
两者对比就是close更暴力些,不过项目开发中另有方法关闭,不用的这两个。
升级版本:
直接在bean要创建的对象的类中实现两个接口InitializingBean, DisposableBean,然后重写接口中的方法destroy和afterPropertiesSet即可,bean中不需要再额外写init-method="" destroy-method=""了。
package dao.impl;
import dao.BookDao;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
public class BookDaoImpl implements BookDao, InitializingBean, DisposableBean {
public void save()
{
System.out.println("book dao save...");
}
@Override
public void destroy() throws Exception
{
System.out.println("system destroy...");
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("system init");
}
}
bean底层实现:
bean底层用的是暴力反射破解要创建的对象的类,调用后者的无参构造方法,所以哪怕后者的构造方法设置成私有,也可以调用。但是如果后者只有有参构造方法,则会报错。