1.IOC控制反转
IOC:(Inversion(反转) Of Control):控制反转;
控制:资源的获取方式;
主动式:(要什么资源都自己创建即可)
BookServlet{
//自己new对象
BookService bs = new BookService();
AirPlane ap = new AirPlane();//复杂对象的创建是比较庞大的工程 }
被动式:资源的获取不是我们自己创建,而是交给一个容器来创建和设置;
BookServlet{
BookService bs;
public void test01(){
bs.checkout();
}
}
容器:管理所有的组件(有功能的类);假设,BookServlet受容器管理,BookService也受容器管理;容器可以自动的探查出那些组件(类)需要用到另一写组件(类);容器帮我们创建BookService对象,并把BookService对象赋值过去; 容器:主动的new资源变为被动的接受资源;
ioc解释
IOC(容器)婚介所: 主动获取变为被动接受; DI:(Dependency Injection)依赖注入: 容器能知道哪个组件(类)运行的时候,需要另外一个类(组件);容器通过反射的形式,将容器中准备好的BookService对象注入(利用反射给属性赋值)到BookServlet中;
只要IOC容器管理的组件,都能使用容器提供的强大功能; HelloWorld;
(通过各种方式给容器中注册对象(注册会员))
以前是自己new 对象,现在所有的对象交给容器创建;给容器中注册组件
1.1getBean的使用
// getBean()获取xml中配置的id(唯一标识)
User user = (User) applicationcontext.getBean("user");
// 方式二根据反射获取 但是只能当只创建一个对象时候有用
// User bean = applicationcontext.getBean(User.class);
// 方式三 根据xml的唯一标识id获取后面加类 (这样就不要类型强转了)
User user1 = applicationcontext.getBean("user", User.class);
// 获取有参构造赋值
User user2 = applicationcontext.getBean("user2", User.class);
// System.out.println(bean);
System.out.println(user2);
System.out.println(user);
System.out.println(user1);
1.2spring配置有参无参构造方法
<?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注册对象 = new对象这里交给容器了
class表示类
id对象名(唯一)
-->
<bean class="com.tc.bean.User" id="user">
<!--
使用property标签为User对象的属性赋值
name="lastName":指定属性名
value="张三":为这个属性赋值
name值是由setter赋值的
-->
<!-- property是通过调用无参 使用getter赋值-->
<property name="id" value="01"/>
<property name="name" value="谭铖"/>
<property name="sex" value="男"/>
<property name="email" value="男"/>
</bean>
<bean class="com.tc.bean.User" id="user2">
<!--
有参构造方法赋值
-->
<constructor-arg name="id" value="2"/>
<constructor-arg name="email" value="email"/>
<constructor-arg name="sex" value="男"/>
<constructor-arg name="name" value="李母猪"/>
</bean>
<!-- 有参构造方法的多种赋值方式-->
<bean class="com.tc.bean.User" id="user3">
<!-- public User(Integer id, String name, String sex, String email) {-->
<!-- 根据value赋值的话必须按照构造方法赋值-->
<constructor-arg value="3"/>
<constructor-arg value="java"/>
<constructor-arg value="女"/>
<constructor-arg value="qq.com"/>
</bean>
<bean class="com.tc.bean.User" id="user4">
<!-- 当顺序不一致可以用index赋值从开始排序赋值-->
<constructor-arg value="3" index="0"/>
<constructor-arg value="tancheng" index="1"/>
<constructor-arg value="qq.com1" index="3"/>
<constructor-arg value="男" index="2"/>
</bean>
<bean class="com.tc.bean.User" id="user5">
<!-- 当有多个有参构造方法的重载的时候 可以利用type写全属性进行赋值-->
<!-- public User( String name, String email,Integer id) {-->
<!-- public User(Integer id, String name, String sex) {-->
<constructor-arg value="tancheng" type="java.lang.String"/>
<constructor-arg value="qq.eam" type="java.lang.String"/>
<constructor-arg value="01" type="java.lang.Integer"/>
</bean>
</beans>
1.3Spring使用p名称空间配置属性
更加方便
<!-- 使用p标签配置命名空间 -->
<bean class="com.tc.bean.User" id="user6"
p:id="22" p:name="tanchengggg"p:email="ewew@qq.cpm" p:sex="nan">
<!-- 通过p:标签命名 要导入xmlns:p="http://www.springframework.org/schema/p"就可以使用了-->
</bean>
1.4类中类使用
bean写全局的可以随处获取
局部的不行局部就不要写id了写了等于没有写呢亲
<!-- 传类的对象赋值方法一-->
<!-- 首先创建好一个Cat类-->
<bean class="com.tc.bean.Cat" id="cat2">
<property name="name" value="奥迪"/>
<property name="price" value="100000"/>
</bean>
<!-- 使用ref直接引用-->
<!-- ref:代表引用外面的一个值 ;引用其他bean car = ioc.getBean("car01") -->
<bean class="com.tc.bean.User" id="user8">
<property name="cats" ref="cat2"/>
</bean>
<!-- 传类的对象赋值方法二-->
<bean class="com.tc.bean.User" id="user7">
<!-- 获取setter方法 套一个bean再赋值-->
<property name="cats">
<!--对象我们可以使用bean标签创建 car = new Car(); 引用内部bean;不能被获取到,只能内部使用 -->
<bean class="com.tc.bean.Cat" id="cat1">
<property name="name" value="宝马"/>
<property name="price" value="10000"/>
</bean>
</property>
</bean>
1.5List集合的赋值
<!--List对象的使用-->
<bean class="com.tc.bean.User" id="user9">
<property name="catList">
<!-- 相当于cats = new ArrayList<Cat>(); -->
<list>
<!-- list标签体中添加每一个元素 -->
<bean class="com.tc.bean.Cat">
<property name="name" value="保时捷"/>
<property name="price" value="22222"/>
</bean>
<!-- 引用外部元素 不能引用别的地方内部bean-->
<ref bean="cat2"/>
</list>
</property>
</bean>
1.6map集合的赋值/Properties对象的使用
<!-- map对象的使用-->
<bean class="com.tc.bean.Cat" id="cat01">
<property name="name" value="西游记"/>
</bean>
<bean class="com.tc.bean.User" id="user10">
<property name="map">
<!-- 相当于创建了map-->
<map>
<!--赋值-->
<entry key="01" value="111"/>
<!-- 外部bean赋值-->
<entry key="02" value-ref="cat01"/>
<!-- 内部bean赋值-->
<entry key="03">
<bean class="com.tc.bean.Cat">
<property name="name" value="洗衣液"/>
<property name="price" value="122"/>
</bean>
</entry>
<!-- value传参-->
<entry key="05">
<value>哈哈哈哈</value>
</entry>
<!-- 套娃 嵌套一个map-->
<entry key="06">
<map>
<entry key="01" value="222"/>
</map>
</entry>
</map>
</property>
<!-- Properties对象的使用-->
<property name="properties">
<!-- properties = new Properties();所有的k=v都是string -->
<props >
<!-- k=v都是string;值直接写在标签体中 -->
<prop key="username">root</prop>
<prop key="password">1234</prop>
</props>
</property>
</bean>
1..6util的使用
<!-- util名称空间创建集合类型的bean;方便别人引用 -->
<!-- 需要引入 xmlns:util="http://www.springframework.org/schema/util"-->
<bean class="com.tc.bean.User" id="user11">
<property name="map" ref="mapUtil"/>
<property name="catList" ref="listUtil"/>
<property name="properties" ref="propertiesUtil"/>
<property name="sets" ref="setUtil"/>
</bean>
<!-- 相当于创建了map 必须设置id-->
<util:map id="mapUtil">
<entry key="01" value="tancheng"/>
<!-- 引用外部bean-->
<entry key="02" value-ref="cat01"/>
<!-- 内部bean-->
<entry key="03">
<bean class="com.tc.bean.Cat">
<property name="name" value="asd"/>
<property name="price" value="22"/>
</bean>
</entry>
<!-- value传参-->
<entry key="05">
<value>哈哈哈哈</value>
</entry>
<!-- 套娃 嵌套一个map-->
<entry key="06">
<map>
<entry key="01" value="222"/>
</map>
</entry>
</util:map>
<!-- util:list-->
<util:list id="listUtil">
<list/>
<value>sssss</value>
<bean class="com.tc.bean.User">
<!-- 为car赋值的时候。改变car的价格 -->
<property name="cats" ref="cat2"/>
<property name="cats.price" value="99000"/>
<property name="map" ref="mapUtil"/>
</bean>
<ref bean="cat2"/>
</util:list>
<!-- util:properties-->
<util:properties id="propertiesUtil">
<prop key="username">xiyang</prop>
<prop key="password">12323</prop>
</util:properties>
<!-- util:set-->
<util:set id="setUtil">
<value>root</value>
<value>10000</value>
</util:set>
1.7属性继承、配置抽象,bean创建的顺讯
<!-- 实验6:通过继承实现bean配置信息的重用 -->
<!--实验7:通过abstract属性创建一个模板bean -->
<!-- abstract="true":这个bean的配置是一个抽象的,不能获取他的实例,只能被别人用来继承 -->
<bean class="com.tc.bean.User" id="user12" abstract="true">
<property name="name" value="tancheng"/>
<property name="sex" value="男"/>
<property name="email" value="qq.com"/>
</bean>
<!-- 继承user12的配置信息 需要改的就改掉-->
<bean id="user13" parent="user12" class="com.tc.bean.User">
<property name="name" value="zhangsan"/>
</bean>
<!--实验8:bean之间的依赖 -->
<!-- 原来是按照配置的顺序创建bean -->
<!-- 改变bean的创建顺序 -->
<!--实验8:bean之间的依赖(只是改变创建顺序) -->
<bean class="com.tc.bean.User" id="user14" depends-on="cat,user12"></bean>
<bean class="com.tc.bean.Cat" id="cat"></bean>
1.8.bean的作用域(单例and多例模式)
<!-- 实验9:测试bean的作用域,分别创建单实例和多实例的bean★bean的作用域:
指定bean是否单实例,xxx;
默认:单实例的
prototype:多实例的:容器启动默认不会去创建对象获取的时候创建对象、每次获取都会创建一个新的对象
singleton:单实例的;默认的 在容器启动完成之前就已经创建好对象,保存在容器中了。任何获取都是获取之前创建好的那个对象;
request:在web环境下,同一次请求创建一个Bean实例(没用)
session:在web环境下,同一次会话创建一个Bean实例(没用)
-->
<bean class="com.tc.bean.User" id="user" scope="prototype"/>
2工厂
2.1静态工厂
创建工厂类
import com.tc.bean.Cat;
/**
* @author 谭铖
* @date 2021/6/8 18:16
* 静态工厂
*/
public class CatStaticFactory {
public static Cat getCat(String name){
System.out.println("CatStaticFactory...");
Cat cat = new Cat();
cat.setName(name);
cat.setPrice(13232312);
return cat;
}
}
配置xml
<!--实验5:配置通过静态工厂方法创建的bean、实例工厂方法创建的bean、FactoryBean★ -->
<!-- bean的创建默认就是框架利用反射new出来的bean实例 -->
<!--
工厂模式;工厂帮我们创建对象;有一个专门帮我们创建对象的类,这个类就是工厂 AirPlane ap = AirPlaneFactory.getAirPlane(String jzName);
静态工厂:工厂本身不用创建对象;通过静态方法调用,对象 = 工厂类.工厂方法名();
实例工厂:工厂本身需要创建对象;工厂类 工厂对象 = new 工厂类(); 工厂对象.getAirPlane("张三"); -->
<!-- 静态工厂-->
<!--
静态工厂(不需要创建工厂本身)factory-method="getCat":指定哪个方法是工厂方法
class:指定静态工厂全类名 factory-method:指定工厂方法
constructor-arg:可以为方法传参
-->
<bean class="com.tc.Factory.CatStaticFactory" id="cat1" factory-method="getCat">
<constructor-arg name="name" value="奥迪"/>
</bean>
2.2实例工厂
创建实例工厂
package com.tc.Factory;
import com.tc.bean.Cat;
/**
* @author 谭铖
* @date 2021/6/8 18:21
*/
public class CatFactory {
public Cat getCat(String name){
System.out.println("CatFactory...");
Cat cat = new Cat();
cat.setName(name);
cat.setPrice(13232312);
return cat;
}
}
配置
<!--实例工厂使用 首先要先创建工厂方法 -->
<bean class="com.tc.Factory.CatFactory" id="catFactory"/>
<!-- 创建bean调用实例工厂
factory-bean:获取创建的实例工厂
factory-method:获取工厂的指定方法
constructor-arg:可以为方法传参
-->
<bean class="com.tc.bean.Cat" id="cat" factory-bean="catFactory" factory-method="getCat">
<!-- constructor-arg:可以为方法传参-->
<constructor-arg name="name" value="宝马"/>
</bean>
2.3FactoryBean
创建类实现FactoryBean
package com.tc.Factory;
import com.tc.bean.Cat;
import org.springframework.beans.factory.FactoryBean;
/**
* @author 谭铖
* @date 2021/6/8 21:02
* 1、编写一个FactoryBean的实现类
* 2、在spring配置文件中进行注册
*/
public class MyFactorylmpl implements FactoryBean<Cat> {
/**
* getObject:工厂方法;
* 返回创建的对象
*/
@Override
public Cat getObject() throws Exception {
System.out.println("MyFactorylmpl。。帮你创建对象...");
Cat cat = new Cat();
cat.setName("保时捷");
return cat;
}
/**
* 返回创建对象的类型
* Spring会自动调用这个方法来确认创建的对象是什么类型
* @return
*/
@Override
public Class<?> getObjectType() {
return Cat.class;
}
/**
* 判断是否是单列多列 但是创建都是获取再创建对象
* false:不是单例
* true:是单例
* @return
*/
@Override
public boolean isSingleton() {
return false;
}
}
配置
<!--
FactoryBean★(是Spring规定的一个接口)只要是这个接口的实现类,Spring都认为是一个工厂;
1、ioc容器启动的时候不会创建实例
2、FactoryBean;获取的时候的才创建对象
-->
<!-- 这里虽然调用的是MyFactorylmpl但是其实是创建的类里面的泛型的值-->
<bean class="com.tc.Factory.MyFactorylmpl" id="myFactorylmpl"/>
2.4bean的生命周期
<!-- 实验10:创建带有生命周期方法的bean 生命周期:bean的创建到销毁;
ioc容器中注册的bean;
1.单例bean,容器启动的时候就会创建好,容器关闭也会销毁创建的bean2)
2.多实例bean,获取的时候才创建;我们可以为bean自定义一些生命周期方法;
spring在创建或者销毁的时候就会调用指定的方法;自定义初始化方法和销毁方法;
init-method:初始化方法
destroy-method:销毁方法
-->
<bean class="com.tc.bean.Cat" id="cat" init-method="init" destroy-method="destroy"/>
cat配置方法
/**
* @author 谭铖
* @date 2021/6/7 22:59
*/
@Data
@AllArgsConstructor
public class Cat {
private String name;
private Integer price;
public Cat() {
System.out.println("cat构造方法");
}
// 初始化方法
public void init(){
System.out.println("初始化");
}
// 销毁方法
public void destroy(){
System.out.println("销毁方法");
}
}
2.5后置处理器
顺序:
容器启动)构造器------后置处理器before..-----初始化方法-----后置处理器after...-----bean初始化完成 无论bean是否有初始化方法;后置处理器都会默认其有,还会继续工作;
使用首先是接口就创建类实现
package com.tc.bean;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
/**
* @author 谭铖
* @date 2021/6/9 16:12
* bean的后置处理器
* 1)、编写后置处理器的实现类
* 2)、将后置处理器注册在配置文件中
*/
public class BeanPost implements BeanPostProcessor {
/**
* 初始化开始之前调用
* @param bean 返回bean
* @param beanName bean在xml中配置的id
* @return 返回bean
* @throws BeansException
*/
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("postProcessBeforeInitialization...【"+beanName+"】" +
"bean将要调用初始化方法了....这个bean是这样:【"+bean+"】");
//初始化之后返回的bean;返回的是什么,容器中保存的就是什么
return bean;
}
/**
* 在初始化之后调用
* @param bean 返回bean
* @param beanName bean在xml中配置的id
* @return 返回bean
* @throws BeansException
*/
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("postProcessAfterInitialization...【"+beanName+"】" +
"bean初始化方法调用完了...AfterInitialization..");
//初始化之后返回的bean;返回的是什么,容器中保存的就是什么
return bean;
}
}
添加xml
只要配置后置处理器不管怎样都会运行
<!--实验11:测试bean的后置处理器:BeanPostProcessorSpring有一个接口:
后置处理器:可以在bean的初始化前后调用方法; -->
<bean class="com.tc.bean.BeanPost" id="beanPost"/>
2.6数据库连接池
!--实验12:引用外部属性文件★依赖context名称空间 -->
<!-- 数据库连接池作为单实例是最好的;一个项目就一个连接池,连接池里面管理很多连接。连接是直接从连接池中拿 -->
<!-- 可以让Spring帮我们创建连接池对象,(管理连接池) -->
<!--加载外部配置文件 固定写法classpath:,表示引用类路径下的一个资源-->
<!--引入数据库配置信息 -->
<!-- <context:property-placeholder location="classpath:jdbc.properties"/>-->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="user" value="root"/>
<property name="password" value="123456"/>
<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/bookshopping?serverTimezone=UTC"/>
<property name="driverClass" value="com.mysql.cj.jdbc.Driver"/>
</bean>
test
public class UserTest04 {
ApplicationContext applicationContext = new
ClassPathXmlApplicationContext("conf/applicationcontext1.xml");
// 数据库连接池
@Test
public void userTest() throws SQLException {
// 获取数据库
DataSource bean = applicationContext.getBean(DataSource.class);
System.out.println(bean.getConnection());
}
}
3.xml的自动装配
<!-- 为Person里面的自定义类型的属性赋值
property:手动赋值自动赋值(自动装配)/自动装配:(仅限于对自定义类型的属性有效)
1)、先按照有参构造器参数的类型进行装配(成功就赋值);没有就直接为组件装配null即可。
2)、如果按照类型找到了多个;参数的名作为id继续匹配;找到就装配;找不到就null;
3)、不会报错;自动的为属性赋值: -->
<bean class="com.tc.bean.Cat" id="cats">
<property name="name" value="baoma"/>
<property name="price" value="23112"/>
</bean>
<!--
autowire="default/no":不自动装配;不自动为car属性赋值 //按照某种规则自动装配
autowire="byName":按照名字;以属性名(car)作为id去容器中找到这个组件,给他赋值;如果找不到就装配null;
autowire="byType":以属性的类型作为查找依据去容器中找到这个组件;如果容器中有多个这葛类型的组件,报错;
autowire="constructor":public Person(Car car) 按照构造器进行赋值首先要创建构造方法;
1)、先按照有参构造器参数的类型进行装配(成功就赋值);没有就直接为组件装配null即可。
2)、如果按照类型找到了多个;参数的名作为id继续匹配;找到就装配;找不到就null;
3)、不会报错;自动的为属性赋值
-->
<bean class="com.tc.bean.User" id="user" autowire="constructor"/>
5.SpEL
Spring表达式语言在SpEL中使用字面量、引用其他bean、引用其他bean的某个属性值、
-
用#{}使用可以完成一些字符串完成不了赋值
<!--
实验14:[SpEL测试I](Spring Expression Language)
Spring表达式语言在SpEL中使用字面量、引用其他bean、引用其他bean的某个属性值、
【 调用非静态方法调用静态方法、】使用运算符;都支持
-->
<bean class="com.tc.bean.User" id="user2">
<!-- 字面量:${}; #{} -->
<property name="name" value="#{10*10}"/>
<!-- 引用其他bean的某个属性值、 -->
<property name="sex" value="#{cats.name}"/>
<!-- 调用非静态方法; 对象.方法名 -->
<property name="email" value="#{cats.getName()}"/>
<!-- 引用其他bean -->
<property name="cats" value="#{cats}"/>
</bean>
4.注解
1.1context:exclude-filter 排除装配组件
1.2context:include-filter 指定装配组件
<!--
使用注解配置步骤
1.业务层等配置好注解
2.添加自动扫描组件 context:component-scan base-package="com.tc"/>
base-package:配置注解类的地址
3.导入AOP jar包 支持注解
-->
<context:component-scan base-package="com.tc" use-default-filters="false" >
<!-- 扫描的时候排除一些组件 context:exclude-filter
type:根据什么排除
annotation 根据注解排除
expression:注解全类名
assignable 排除具体的某个类
expression: 类全类名
-->
<context:exclude-filter type="assignable" expression="org.springframework.stereotype.Repository"/>–>-->
<!--
context:include-filter 只扫描那些组件
指定只扫描哪些组件,默认是全都扫描进来
所以需要设置use-default-filters="false"
-->
<context:include-filter type="assignable" expression="org.springframework.stereotype.Repository" />
</context:component-scan>
1.3配置
-
数据库层(DAO) @Repository
-
业务层(service) @Service
-
控制器(Servlet) @Controller
-
全部层可以配置 @Component
/**
* @author 谭铖
* @date 2021/6/10 15:06
* 持久层数据库层用@Repository
* 注解类未配置id id为类名的首字母小写 注解前面加括号可以自定义id
*/
@Repository("password")
/**
* 单实例 singleton
* 多实例 prototype
*/
@Scope("prototype")
public class UserDAO {
}
2.依赖注入 @Autowired自动装配
//servlet层
@Controller
public class UserServlet {
/**
* 如果不去new对象就会空指针异常java.lang.NullPointerException
* 用spring就可以自动装配了用注解@Autowired
*/
@Autowired
private UserService userService;
public void save(){
System.out.println("调用userService");
userService.save();
}
}
//service层
@Service
public class UserService {
@Autowired
private UserDAO userDAO;
public void save() {
System.out.println("调用userDAO");
userDAO.create();
}
}
//DAO层
@Repository("password")
/**
* 单实例 singleton
* 多实例 prototype
*/
@Scope("prototype")
public class UserDAO {
public void create() {
System.out.println("保存用户");
}
}
<!-- 依赖注入 @Autowired自动装配 装配全部-->
<context:component-scan base-package="com.tc"/>
2.设置两个相同的service
//父类
@Service
public class UserService {
@Autowired
private UserDAO userDAO;
public void save() {
System.out.println("调用userDAO");
userDAO.create();
}
}
//子类
@Service
public class UserService01 extends UserService {
@Autowired
private UserDAO userDAO;
@Override
public void save() {
System.out.println("UserService01");
userDAO.create();
}
}
public class UserServlet {
/**
* 如果不去new对象就会空指针异常java.lang.NullPointerException
* 用spring就可以自动装配了用注解@Autowired
* 自动装配的步骤
* 1.按照类的找
* 找到装配/没找到异常
* 找到多个 按照类名首字母小写为id找
* 找不到异常 可以用@Qualifier("userService01")在里面输入类名首字母小写的id
* 如果@Qualifier()配置的id不存在就会报异常
* 可以配置注解@Autowired(required = false)找不到赋值为null
*
*/
// 自动装配配置为required的话找不到赋值变null
@Autowired(required = false)
// 使用类名首字母小写的为id配置
@Qualifier("userService011")
private UserService userService011;
public void save(){
System.out.println("调用userService"+userService011);
}
}
2方法也可以配置自动装配
/**
* 方法也可以自动装配
* 在bean创建的时候就会运行
* 方法上传的参数都会赋值
*/
@Autowired(required = false)
public void test(UserDAO userDAO, @Qualifier("userService") UserService userService){
System.out.println("spring运行:"+userDAO+"and"+userService);
}
3.@Autowired 和@Resource的区别
@Resource是javaee的标准 在哪里都可以用 扩展性强
3.spring的单元测试
4.自动装配泛型
1.dao层配置一个baseDAO抽象方法
public abstract class baseDAO<T> {
// 抽象方法
public abstract void save();
}
2.dao层catDAO继承baseDAO
/**
* @author 谭铖
* @date 2021/6/11 1:37
* 数据库层装配
*/
@Repository
public class CatDAO extends baseDAO<Cat>{
@Override
public void save() {
System.out.println("购物车");
}
}
3.service层baseService通用类
public class baseService<T> {
// 自动装配
@Autowired
baseDAO<T> baseDAO;
public void save(){
baseDAO.save();
}
}
4.继承baseService
/**
* @author 谭铖
* @date 2021/6/11 1:41
*/
@Service
public class CatService extends baseService<Cat>{
}
5.xml装配
<!-- 依赖注入 @Autowired自动装配-->
<context:component-scan base-package="com.tc"/>