spring从入门到精通

一、准备工作:

说明:本spring实例基于spring2.5.6。

1.新建实体类com.hanjun.entity.User。有以下属性及getter、setter方法:

 private String username;
 private String password;

2.新建DAO接口com.hanjun.dao.UserDao。声明方法:

public void save(User user);

3.新建DAO接口实现类com.hanjun.dao.impl.UserDaoImpl。实现方法:

 public void save(User user) {
  System.out.println("user saved!");
 }

4.新建service类com.hanjun.service.UserService。声明UserDao属性及getter、setter和add方法:

 private UserDAO userDAO;  
 public void add(User user) {
  userDAO.save(user);
 }

二、模拟spring注入

1.src下新建beans.xml,内容如下:

 <?xml version="1.0" encoding="UTF-8"?>
 <beans>
  <bean id="u" class="com.hanjun.dao.impl.UserDAOImpl" />
  <bean id="userService" class="com.hanjun.service.UserService" >
   <property name="userDAO" bean="u"/>
  </bean>
 </beans>

2.新建interface com.hanjun.spring.BeanFactory,声明方法:

 public Object getBean(String id);

3.新建class com.hanjun.spring.ClassPathXmlApplicationContext 实现com.hanjun.spring.BeanFactory:

 //用于存放xml中配置的bean
 private Map<String, Object> beans = new HashMap<String, Object>();
 //初使化时解析xml中配置的bean,存入beans
 public ClassPathXmlApplicationContext() throws Exception {
  SAXBuilder sb = new SAXBuilder();
  Document doc = sb.build(this.getClass().getClassLoader().getResourceAsStream("beans.xml")); // 构造文档对象
  Element root = doc.getRootElement(); // 获取根元素
  List list = root.getChildren("bean");// 取名字为bean的所有元素
  for (int i = 0; i < list.size(); i++) {
   Element element = (Element) list.get(i);
   String id = element.getAttributeValue("id"); //获取bean的id属性值
   String clazz = element.getAttributeValue("class");//获class属性值
   Object o = Class.forName(clazz).newInstance();
   beans.put(id, o);
   for (Element propertyElement : (List<Element>) element.getChildren("property")) {
    String name = propertyElement.getAttributeValue("name"); // userDAO
    String bean = propertyElement.getAttributeValue("bean"); // u
    Object beanObject = beans.get(bean);// UserDAOImpl instance
    String methodName = "set" + name.substring(0, 1).toUpperCase() + name.substring(1);
    Method m = o.getClass().getMethod(methodName,beanObject.getClass().getInterfaces()[0]);
    m.invoke(o, beanObject);
   }
  }
 }
 public Object getBean(String id) {
  return beans.get(id);
 }

4.测试:

 BeanFactory applicationContext = new ClassPathXmlApplicationContext();
 UserService service = (UserService)applicationContext.getBean("userService");
 User u = new User();
 u.setUsername("zhangsan");
 u.setPassword("zhangsan");
 service.add(u);


5.说明:此例有bug,因为加载bean时为顺序从上往下,所以被注入的bean需配置在上面。解析xml需要jdom.jar。

三、注入(xml)

1.引入spring.jar和commons-logging.jar

2.src下新建applicationContext.xml,内容如下:

 <?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-2.5.xsd">
 
   <bean id="u" class="com.hanjun.dao.impl.UserDAOImpl"></bean>
  
   <bean id="userService" class="com.hanjun.service.UserService">
     <property name="userDAO" ref="u" />
   </bean>
 </beans>


3.测试代码:

 ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
 UserService service = (UserService)ctx.getBean("userService");
 User u = new User();
 u.setUsername("zhangsan");
 u.setPassword("zhangsan");
 service.add(u);

4.我们常用的就是setter注入方式,spring还支持构造方法注入方式:

  <bean id="userService" class="com.hanjun.service.UserService">
   <constructor-arg ref="u"></constructor-arg>
  </bean>

spring将id为u的bean做为参数调用UserService类对应的构造方法。如果参数不止一个,则可以通过参数类型或索引区分:

   <constructor-arg type="int" value="1"></constructor-arg>
   <constructor-arg type="java.lang.String" value="str"></constructor-arg>

   <constructor-arg index="0" value="1"></constructor-arg>
   <constructor-arg index="1" value="str"></constructor-arg>

5.简单类型注入和集合类型注入,为简单类型变量注入值:

<property name="score" value="99" />

为Set类型变量注入值:

   <property name="sets">
    <set>
     <value>1</value>
     <value>2</value>
    </set>
   </property>

为List类型变量注入值:

   <property name="lists">
    <list>
     <value>1</value>
     <value>2</value>
     <value>3</value>
    </list>
   </property>

为Map类型变量注入值:

   <property name="maps">
    <map>
     <entry key="1" value="1"></entry>
     <entry key="2" value="2"></entry>
     <entry key="3" value="3"></entry>
     <entry key="4" value="4"></entry>
    </map>
   </property>

为Properties类型变量注入值:

   <property name="propertys">
    <props>
     <prop key="1">1</prop>
     <prop key="2">2</prop>
     <prop key="3">3</prop>
     <prop key="4">4</prop>
    </props>
   </property>

四、注入(annotation)

1.applicationContext.xml中,beans标签如下,蓝色部分为新增。

<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-2.5.xsd
           http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context-2.5.xsd
">

2.beans中增加配置如下:

 <context:annotation-config />

3.在要注入的setter方法上注解@Autowired,则spring会根据参数类型找到对应类型的bean为参数,如果对应类型的bean大于1个,则会出错。解决办法为在参数类型前注解@Qualifier("bean的id或name")指定要注入哪个bean。

 @Autowired
 public void setUserDAO(@Qualifier("u") UserDAO userDAO) {
  this.userDAO = userDAO;
 }

4.相对于@Autowired,还有另一种注解方式。在要注入的setter方法上注解@Resource,spring会首先根据setter方法的名字找对应的bean做为参数,如果找不到则再根据参数的类型找对应类型的bean做为参数。@Resource(name="bean的id或name")则可以指定注入哪个bean。@Resource所用的是javax.annotation.Resource类,此类在jdk1.6引入,所以当使用jdk1.6以下版本时,想用@Resource,需引入common-annotations.jar。

5.bean的注解方式:applicationContext.xml的beans中增加配置:

<context:component-scan base-package="com.hanjun"/>

然后在需要配置class类上面注解@Component,则spring初使化时会扫描指定包下的所有类,对有此注解的类自动初使化为spring的bean类,name为类名(第一个字母小写)。@Component("bean的name")则可指定bean的name。

附录,已有bean的实例如何获取bean的id

  ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
  IUserDao userDao = ctx.getBean(IUserDao.class);
  for(String beanId :ctx.getBeanNamesForType(IUserDao.class)){
      if(ctx.getBean(beanId)==userDao){
          System.out.println(beanId);
      }
  }

五、bean的属性

1.scope:初使化方式。默认值为singleton,即每次获取的bean为同一个。当值为prototype时,每次获取都new一个新的类。对于struts的action类,常设置为prototype。

annotation方式:class上注解@Scope("prototype")。

2.autowire:自动注入。默认值为no,即不自动注入。当值为byType时,spring会根据参数类型找对应类型的bean做为参数,如果对应类型的bean多于1个,则会出错。当值为byName时,spring会根据setter方法的名字找对应id或name的bean做为参数,例如根据setStu方法找id或name为stu的bean做为参数。

annotation方式:见spring注入(annotation)

3.lazy-init:懒加载。默认值为false,即在spring初使化时就初使化此bean。当值为true时,则当使用到此bean时才初使化。

4.init-method="方法名":bean初使化时运行此方法。

annotation方式:在方法上注解@PostConstruct。

5.destroy-method="方法名":bean销毁时运行此方法。

annotation方式:在方法上注解@PreDestroy。

六、动态代理(jdk)

要求:在执行UserDaoImpl的所有方法前,打印"方法名 strat"。

1.新建class com.hanjun.aop.LogInterceptor。实现java.lang.reflect.InvocationHandler接口:

 private Object target;
 
 public Object getTarget() {
  return target;
 }
 public void setTarget(Object target) {
  this.target = target;
 }
 public void beforeMethod(Method m) {
  System.out.println(m.getName() + " start");
 }
 public Object invoke(Object proxy, Method m, Object[] args)
   throws Throwable {
  beforeMethod(m);
  m.invoke(target, args);
  return null;
 }

2.测试代码:

  UserDAO userDAO = new UserDAOImpl();
  LogInterceptor li = new LogInterceptor();
  li.setTarget(userDAO);
  UserDAO userDAOProxy = (UserDAO)Proxy.newProxyInstance(userDAO.getClass().getClassLoader(), userDAO.getClass().getInterfaces(), li);
  userDAOProxy.save(new User());

3.这样,就由我们写的LogInterceptor类来代理执行UserDaoImpl类的方法,可以在invok方法内任意增加代码。需要注意的是,被代理的方法必须是实现接口的方法。

七、aop(xml)

1.applicationContext.xml中,beans标签如下,蓝色部分为新增。如果被代理的方法不是实现接口的方法,还需要导入cglib-nodep-2.1_3.jar。

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

2.新建com.hanjun.aop.LogInterceptor类:

public class LogInterceptor {
 public void before() {
  System.out.println("method before");
 }
}

3.beans中增加配置:

 <bean id="logInterceptor" class="com.hanjun.aop.LogInterceptor"></bean>
 <aop:config>
  <aop:aspect id="logAspect" ref="logInterceptor">
   <aop:before method="before" pointcut="execution(public void com.hanjun.service.UserService.add(com.bjsxt.model.User))" />
  </aop:aspect>
 </aop:config>

4.测试代码:

  ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
  UserService service = (UserService)ctx.getBean("userService");
  service.add(new User());

5.打印结果:

method before
user saved!

6.说明:spring的aop类需要配置为bean。aop的配置写在aop:config内。aop:aspect的ref属性指定对哪个aop类进行配置。aop:before标签的methode属性指定的方法会在pointcut织入点语句指定的对象执行前执行。

7.织入点语法:

execution(* sa* (..))  任何返回值,任何包下的以sa为命名开始的方法;

execution(* com.hanjun.dao.impl.UserDAOImpl.*(..))  指定类的任何方法;

execution(* com.hanjun.dao.impl.*.*(..))  指定包下的任何类的任何方法;

execution(* com.hanjun.dao..*.*(..))  指定包下的任何子包下的任何类的任何方法;

8.其它advice:

<aop:after-returning method="方法名" pointcut="织入点语句"/> 指定对象执行后执行指定方法

<aop:after-throwing method="方法名" pointcut="织入点语句"/>  指定对象执行出现异常时执行指定方法

9.如果多个aop的配置用同样的织入点语句,则可以在aop:config配置aop:pointcut,expression属性指定织入点语句,id为引用标识。aop:before的pointcut-ref等于aop:pointcut的id:

 <aop:config>
  <aop:pointcut expression="execution(* com.bjsxt.service.*.*(..))" id="servicePointuct"/>
  <aop:aspect id="logAspect" ref="logInterceptor">
   <aop:before method="before" pointcut-ref="servicePointuct" />
  </aop:aspect>
 </aop:config>

10.环绕拦截:在com.hanjun.aop.LogInterceptor中增加方法:

 public void aroundMethod(ProceedingJoinPoint pjp) throws Throwable {
  System.out.println("method around start");
  pjp.proceed();
  System.out.println("method around end");
 }

在aop:config标签中增加配置:

<aop:around method="aroundMethod" pointcut="execution(* com.bjsxt.service.*.*(..))"/>

11.说明:如果被代理的方法为实现接口的方法,spring会用jdk的动态代理方式。如果不是实现接口的方法,需要导入cglib-nodep-2.1_3.jar,则spring会直接操作二进制码来实现代理。

八、aop(annotation)

1.引入aspectjrt.jar和aspectjweaver.jar。

2.applicationContext.xml中,beans标签如下,蓝色部分为新增。

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

3.beans中增加配置:

<aop:aspectj-autoproxy />

4.新建com.hanjun.aop.LogInterceptor类:

@Aspect
@Component
public class LogInterceptor {
 @Before("execution(public void com.hanjun.dao.impl.UserDAOImpl.save(com.hanjun.entity.User))")
 public void before() {
  System.out.println("method before");
 }
}

5.测试代码:

  ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
  UserService service = (UserService)ctx.getBean("userService");
  service.add(new User());

6.打印结果:

method before
user saved!

7.说明:在类上注解了@Aspect的类为spring的aop类;aop类本身也要spring管理,所以在类上注解@Component;在aop类的方法上注解@Before("织入点语句")则会在织入点语法指定对象运行前执行此方法。

8.织入点语法:

execution(* sa* (..))  任何返回值,任何包下的以sa为命名开始的方法;

execution(* com.hanjun.dao.impl.UserDAOImpl.*(..))  指定类的任何方法;

execution(* com.hanjun.dao.impl.*.*(..))  指定包下的任何类的任何方法;

execution(* com.hanjun.dao..*.*(..))  指定包下的任何子包下的任何类的任何方法;

9.其它advice:

@AfterReturning("织入点语句")  在织入点语句指定的对象执行完之后执行;

@AfterThrowing("织入点语句")  在织入点语句指定的对象执行出现异常时执行;

10.如果多个方法用的织入点语句相同,则可以用给一个空方法注解@Pointcut("织入点语句"),下面可以用这个方法名来共用织入点语句:

 @Pointcut("execution(* com.hanjun.dao..*.*(..))")
 public void myMethod(){}
 @AfterReturning("myMethod()")
 public void after() {
  System.out.println("method after");
 }

11.环绕拦截:

 @Around("execution(* com.bjsxt.dao..*.*(..)))")
 public void around(ProceedingJoinPoint pjp) throws Throwable{
  System.out.println("around start");
  pjp.proceed();
  System.out.println("around end");
 }

12.说明:如果被代理的方法为实现接口的方法,spring会用jdk的动态代理方式。如果不是实现接口的方法,需要导入cglib-nodep-2.1_3.jar,则spring会直接操作二进制码来实现代理。

九、datasource注入

在mysql数据库新建test数据库,新建表t_user,列userid、username、password。

1.在applicationContext.xml的beans标签中增加配置:

 <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
  <property name="driverClassName" value="com.mysql.jdbc.Driver" />
  <property name="url" value="jdbc:mysql://localhost:3306/test" />
  <property name="username" value="root" />
  <property name="password" value="root" />
 </bean>

2.引入mysql-connector-java-5.1.13-bin.jar和spring的commons-dbcp.jar、commons-pool.jar。

3.在com.hanjun.dao.impl.UserDAOImpl类中新增DataSource属性和修改save方法:

 private DataSource dataSource;
 public DataSource getDataSource() {
  return dataSource;
 }
 @Resource
 public void setDataSource(DataSource dataSource) {
  this.dataSource = dataSource;
 }
 
 public void save(User user) {
  try {
   String sql="insert into user values(null,'zhangsan','123456')";
   Connection conn=dataSource.getConnection();
   conn.createStatement().executeUpdate(sql);
   conn.close();
  } catch (SQLException e) {
   e.printStackTrace();
  }
 }

4.这样,就可以通过spring注入的dataSource来获取Connection。

5.数据库的属性可以另外配置,src下新建jdbc.properties:

jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/test
jdbc.username=root
jdbc.password=root

applicationContext.xml的beans标签中增加配置:

 <bean
  class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
  <property name="locations">
   <value>classpath:jdbc.properties</value>
  </property>
 </bean>

修改dataSource的配置:

 <bean id="dataSource" destroy-method="close"
  class="org.apache.commons.dbcp.BasicDataSource">
  <property name="driverClassName" value="${jdbc.driverClassName}" />
  <property name="url" value="${jdbc.url}" />
  <property name="username" value="${jdbc.username}" />
  <property name="password" value="${jdbc.password}" />
 </bean>

十、sessionFactory注入

1.引入hibernate的jar包。

2.在com.hanjun.entity包下新建User.hbm.xml,对User类进行hibername的实体类配置。

3.在spring的applicationContext.xml的beans标签中,增加sessionFactory的配置,将spring管理的dataSource注入进来:

 <bean id="sessionFactory"
  class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
  <property name="dataSource" ref="dataSource" />
  <property name="mappingResources">
   <list>
    <value>com/hanjun/entity/User.hbm.xml</value>
   </list>
  </property>
  <property name="hibernateProperties">
   <props>
    <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
    <prop key="hibernate.show_sql">true</prop>
   </props>
  </property>
 </bean>

mappingResources属性指定hibernate实体类的配置文件列表。hibernateProperties属性指定hibernate的属性配置。如果hibernate用annotation配置实体类,则sessionFactory的class改为org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean,属性mappingResources改为annotatedClasses,list的值改为类列表,如com.hanjun.entity.User。或用packagesToScan属性让spring去扫描哪些是hibernate实体类:

  <property name="packagesToScan">
   <list>
    <value>com.hanjun.entity</value>
   </list>
  </property>

4.修改com.hanjun.dao.impl.UserDAOImpl类:

 private SessionFactory sessionFactory;
 public SessionFactory getSessionFactory() {
  return sessionFactory;
 }
 
 @Resource
 public void setSessionFactory(SessionFactory sessionFactory) {
  this.sessionFactory = sessionFactory;
 }
 
 public void save(User user) {
  Session s = sessionFactory.openSession();
  s.beginTransaction();
  s.save(user);
  s.getTransaction().commit();
  s.close();
 }

5.测试代码:

  ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
  UserService service = (UserService)ctx.getBean("userService");
  System.out.println(service.getClass());
  User u=new User();
  u.setUsername("zhangsan");
  u.setPassword("123456");
  service.add(u);

十一、管理hibernate事务

1.在applicationContext.xml中,beans标签如下,蓝色部分为新增。

<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:tx="http://www.springframework.org/schema/tx"
 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
           http://www.springframework.org/schema/tx 
           http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
">

2.在beans中增加配置:

 <bean id="txManager"
  class="org.springframework.orm.hibernate3.HibernateTransactionManager">
  <property name="sessionFactory" ref="sessionFactory" />
 </bean>

如果用annotation配置事务,还需要增加配置:

<tx:annotation-driven transaction-manager="txManager"/>

3.修改com.hanjun.dao.impl.UserDAOImpl的save方法,sessionFactory.openSession()改为sessionFactory.getCurrentSession(),不需要打开和提交事务:

 public void save(User user) {
  Session s = sessionFactory.getCurrentSession();
  s.save(user);
 }

4.在com.hanjun.service.UserService的add方法上注解@Transactional:

 @Transactional
 public void add(User user) {
   userDAO.save(user);
   Log log = new Log();
   log.setMsg("a user saved!");
   logDAO.save(log);
 }

5.说明:新增的Log类和logDAO类,在操作用户后记录日志,不详述。如此,如果在记录日志时出现异常,则新加的用户会回滚。

6.transaction的属性:

propagation : @Transactional(propagation=Propagation.REQUIRED),默认为Propagation.REQUIRED,代表如果已经有transaction,则会用这个transaction,如果没有,则会新建一个transaction。当值为Propagation.MANDATORY时,代表必须已经有transaction,如果没有会报错。当值为Propagation.REQUIRES_NEW时,代表这个方法用独立内嵌的transaction,如果回滚不会影响外面的transaction。当值为Propagation.NEVER时,代表外面必须不能有transaction,如果有则会报错。

readOnly : @Transactional(readOnly=true),默认为false,如果为true,代表本事务内没有插入、修改、删除的操作,如果有则报错。此属性主要用于优化。

timeout : @Transactional(timeout=60),如果这个transaction执行超过60秒,则终止掉。

7.xml方法:

 <bean id="txManager"
  class="org.springframework.orm.hibernate3.HibernateTransactionManager">
  <property name="sessionFactory" ref="sessionFactory" />
 </bean>

 <tx:advice id="txAdvice" transaction-manager="txManager">
  <tx:attributes>
   <tx:method name="getUser" read-only="true" />
   <tx:method name="add*" propagation="REQUIRED"/>
  </tx:attributes>
 </tx:advice>

 <aop:config>
  <aop:pointcut id="bussinessService"
   expression="execution(public * com.hanjun.service..*.*(..))" />
  <aop:advisor pointcut-ref="bussinessService"
   advice-ref="txAdvice" />
 </aop:config>

十二、hibernateTemplate注入

1.applicationContext.xml的beans中增加配置:

 <bean id="hibernateTemplate" class="org.springframework.orm.hibernate3.HibernateTemplate">
  <property name="sessionFactory" ref="sessionFactory"></property>
 </bean>

2.修改com.hanjun.dao.impl.UserDAOImpl:

 private HibernateTemplate hibernateTemplate;
 public HibernateTemplate getHibernateTemplate() {
  return hibernateTemplate;
 }
 @Resource
 public void setHibernateTemplate(HibernateTemplate hibernateTemplate) {
  this.hibernateTemplate = hibernateTemplate;
 }
 public void save(User user) {
  hibernateTemplate.save(user);
 }

3.这样,在执行数据库操作时,直接操作就可以了,其它的不需要考虑。

4.org.springframework.orm.hibernate3.support.HibernateDaoSupport可以管理HibernateTemplate:

新建com.hanjun.dao.SuperDAO:

@Component
public class SuperDAO extends HibernateDaoSupport {
 @Resource(name="sessionFactory")
 public void setSuperSessionFactory(SessionFactory sessionFactory) {
  super.setSessionFactory(sessionFactory);
 }
}

则com.hanjun.dao.impl.UserDAOImpl不再需要hibernateTemplate属性,直接写方式即可:

@Component("userDAO") 
public class UserDAOImpl extends SuperDAO implements UserDAO {
 
 public void save(User user) {
  this.getHibernateTemplate().save(user);
 }
 
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值