spring配外部文件
我们先在Spring里配置一个数据源
1.导c3p0包,这里我们先学一下hibernate持久化框架,以后用mybites.
<dependency><groupId>org.hibernate</groupId><artifactId>hibernate-core</artifactId><version>5.2.17.Final</version></dependency><dependency><groupId>org.hibernate</groupId><artifactId>hibernate-c3p0</artifactId><version>5.3.0.Final</version></dependency>
2.安装mysql 8.x数据库(参考相关资料),导入驱动包
<dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.16</version></dependency>
3.看具体代码:
<!-- 配置c3p0,ComboPooledDataSource对象,它指向一个数据源 --><bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"><property name="user" value="root"></property><property name="password" value="xiong"></property><property name="jdbcUrl" value="jdbc:mysql://124.220.60.104:3306/spring5"></property><property name="driverClass" value="com.mysql.cj.jdbc.Driver"></property></bean>
测试数据库连接
@Testpublic void dataSourcetest() throws SQLException{ApplicationContext ct = new ClassPathXmlApplicationContext("dataSource.xml");DataSource dataSource = (DataSource)ct.getBean("dataSource");System.out.println(dataSource.getConnection());}
-----------------------------------------------------------------
com.mchange.v2.c3p0.impl.NewProxyConnection@45c7e403 [wrapping: com.mysql.cj.jdbc.ConnectionImpl@2925bf5b] //连接成功,产生一个代理数据库服务器
上面这样配置,写死了数据是相对以后转生产环境中修改是十分不方便的,生产环境中,我们极有可能会把dao层打jar包,又分成多模块开发,所以修改起来是十分麻烦,所以我们会把值写成键值对的形式单独保存到一个文件中
使用外部文件保存数据值,再配spring配置文件
jdbc.properties
jdbc.user=root
jdbc.password=xiong
jdbc.url=jdbc:mysql://124.220.60.104:3306/spring5
jdbc.driverClass=com.mysql.cj.jdbc.Driver
dataSouce.xml–spring配置文件
<!-- 配置c3p0,ComboPooledDataSource对象,它指向一个数据源 --><context:property-placeholder location="classpath:jdbc.properties"/><bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"><property name="user" value="${jdbc.user}"></property><property name="password" value="${jdbc.password}"></property><property name="jdbcUrl" value="${jdbc.url}"></property><property name="driverClass" value="${jdbc.driverClass}"></property></bean>
Spring的表达式语言spEL
Spring表达式语言(SpEL):是一个支持运行时查询和操作对象图的强大表示是语言,是一种可以与一个基于spring的应用程序中的运行时对象交互的东西。总得来说SpEL表达式是一种简化开发的表达式,通过使用表达式来简化开发,减少一些逻辑、配置的编写。
语法类似于 EL:SpEL 使用 #{…} 作为定界符 , 所有在大括号中的字符都将被认为是 SpEL , SpEL 为 bean 的属性进行动态赋值提供了便利。
通过 SpEL 可以实现:
通过 bean 的 id 对 bean 进行引用,用了SpEL在bean标签中可以用value代替ref。
可以像EL一样用点运算符调用方法以及对象中的属性。
计算表达式的值
正则表达式的匹配。
SpEL 字面量,意义不大,spring内部本身有数据类型的自动转换机制,直接写值就好了,不必用SqEL,了解:
整数:#{8} 实际上,直接写成“8”即可,如前面讲的:p:id="1",就表示1
小数:#{8.8}
科学计数法:#{1e4}
String:可以使用单引号或者双引号作为字符串的定界符号。
Boolean:#{true}
SpEL引用bean , 调用它属性和方法:
引用其他对象:#{car}
引用其他对象的属性:#{car.price}
调用其它方法 , 还可以链式操作:#{person.pet.toString()}
调用静态方法静态属性:#{T(java.lang.Math).PI}
Spring EL 操作List、Map集合取值//SpEL支持的运算符号:算术运算符:+,-,*,/,%,^(加号还可以用作字符串连接)
比较运算符:< , > , == , >= , <= , lt , gt , eg , le , ge
逻辑运算符:and , or , not , |
if-else 运算符(类似三目运算符):?:(temary), ?:(Elvis)
正则表达式:#{admin.email matches '[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,4}'}
例:引用对象举例
为了测试,我在Pet类中,添加成员属性private double price
及get/set方法,在Person类中添属性成员private double petPrice,private double pi
及get/set方法,petPrice属性在spring创建对象时,引用Pet对象中定义的值,pi属性引用lang包中的静态成员常量。
<!-- springEL,测试 --><bean id="cat1" class="cn.ybzy.springdemo.model.Pet" p:id="1" p:type="cat" p:price="1000.0"></bean><bean id="person" class="cn.ybzy.springdemo.model.Person"><property name="id" value="1"></property><property name="pet" value="#{cat1}"></property><property name="petPrice" value="#{cat1.price}"></property><property name="pi" value="#{T(java.lang.Math).PI}"></property></bean>
/** spring EL 测试*/@Testpublic void springEltest() {ApplicationContext ct = new ClassPathXmlApplicationContext("springEL.xml");Person person=(Person)ct.getBean("person");System.out.println(person);System.out.println(person.getPi());}
--------------------------------------------------------------------
Person [id=1, pet=Pet [id=1, type=cat, price=1000.0], cars=null, petPrice=1000.0]
3.141592653589793
例:springEL运算符演示,这里我只举,三目运算会和正则表达式匹配运算
为了测试,我在Person类中添加test属性,private String test
及get/set方法,它会根根价格来作两个判 断,大于800元,是土豪,小于100元是普通人养宠物。
<property name="test" value="#{cat1.price > 800 ? '土豪' : '普通人'}"></property>
System.out.println(person.getTest());
---------------------------------------------------------------------
土豪
正则表达式测试,字符串 ''aaaa98734"不全是数字,所以匹配0-9多个数字是错的
<property name="test" value="#{'aaa98734' matches '[0-9]+'}"></property>
System.out.println(person.getTest());
---------------------------------------------------------------------
false
例:引用List,Map
map[‘1’]中的1是KEY
Spring通过工厂方法进行配置
在Spring的世界中, 我们通常会利用 xml配置文件 或者 annotation注解方式来配置bean实例!
在第一种利用 xml配置文件 方式中, 还包括如下三小类
- 反射模式(我们前面的所有配置都是这种模式)
- 工厂方法模式
- Factory Bean模式
工厂方法进行配置
静态工厂方法方式是非常适用于作为1个bean容器, 只不过bean集合定义在工厂类里面而不是项目xml配置文件里面。
缺点也比较明显, 把数据写在class里面而不是配置文件中违反了我们程序猿的常识和spring的初衷。当然优点就是令人恶心的xml配置文件更加简洁。所以,工厂方法的配置,了解一下就行了,个人建议不要在项目中使用,但要了解,以后看到项目中有这样的方式,能看得懂。
FactoryBean 来配置Bean
spring通过FactoryBean配置,比前面的工厂方法配置Bean要重要些,因为我们整合很多第三方的框架的时候,需要用到FactoryBean来配置第三方框架中的bean 对象,从而把第三方框架整合到spring中来!当然在整合这些第三方框架的时候,这个FactoryBean一般都是我们引入的jar包中,人家给写好了的,我们会用就行,但知道原理也是好的!
例:通过FactoryBean接口的实现类CarFactoryBean,spring中配Car的bean:id="bwn"是CarFactoryBean的bean名,再通过构造方法注入Car的bean,则试:输出Car对象的toString()中的内容
CarFactoryBean.java
public class CarFactoryBean implements FactoryBean<Car>{private String type;public CarFactoryBean(String type) {this.type=type;}//返回我们要配置的Bean 对象@Overridepublic Car getObject() throws Exception {return new Car(101,type);}//返回我们配置的Bean 对象的类型@Overridepublic Class<?> getObjectType() {return Car.class;}
Car.java
public class Car {private int id;private String mark; //品牌//get/set/toString,方法
}
factoryBean.xml
<!-- 通过FactoryBean实现类CarFactoryBean,来注入一个宝码的Car实例对象 --><bean id="bwm" class="cn.ybzy.springdemo.model.CarFactoryBean"><constructor-arg value="BWM"></constructor-arg><!-- 构造方法注入,当然也可属性注入,但我没有写type的set方法 --></bean>
测试类中:
@Testpublic void FactoryBeantest() {ConfigurableApplicationContext ct = new ClassPathXmlApplicationContext("factoryBean.xml");Car baomaCar = (Car) ct.getBean("bwm");System.out.println(baomaCar);}
----------------------------------------------------------------------------------------------------------------
Car [id=101, mark=BWM]
通过整合Quartz框架-定时做事用的,来演示看看,实际项目应用中,是怎么用FactoryBean来将第三方框架整合进入spring的!
1、导入spring-context-support,quartz等相关jar包
<dependency><groupId>org.quartz-scheduler</groupId><artifactId>quartz</artifactId><version>2.2.1</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-context-support</artifactId><version>5.0.6.RELEASE</version></dependency><dependency><groupId>org.slf4j</groupId><artifactId>slf4j-api</artifactId><version>1.7.35</version></dependency><!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-nop --><dependency><groupId>org.slf4j</groupId><artifactId>slf4j-nop</artifactId><version>1.7.35</version><scope>test</scope>
</dependency>
2、定义一个工作任务job
public class MyJob implements Job{@Overridepublic void execute(JobExecutionContext context) throws JobExecutionException {System.out.println("quartz我的具体的每次工作任务");}}
3、Spring配置文件中整合配置:
1)定义工作任务的Job
2)定义触发器Trigger,并将触发器与工作任务绑定
3)定义调度器,并将Trigger注册到Scheduler
!-- 定义工作任务的Job bean --><bean id="myJob" class="org.springframework.scheduling.quartz.JobDetailFactoryBean"><!-- 指定job的名称 --><property name="name" value="myQuartzJob"></property><!-- 指定job的分组 --><property name="group" value="myJobGroup"></property><!-- 指定具体的job类 --><property name="jobClass" value="cn.ybzy.springdemo.model.MyJob"></property><!-- 必须置为true,如果为false ,当没有活动的触发器与之关联时会在调度器中会删除该任务 --><property name="durability" value="true"></property><!--springIOC容器的KEY --><property name="applicationContextJobDataKey" value="factoryBean"></property></bean><!-- 定义触发器Trigger,并将触发器与工作任务绑定 --><bean id="trigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean"><property name="name" value="myTrigger"></property><property name="group" value="myGroup"></property><!-- 指定Trigger绑定的job --><property name="jobDetail" ref="myJob"></property><!-- 指定Cron的表达式,当前是每隔3秒运行一次 --><property name="cronExpression" value="0/3 * * * * ?"></property></bean><!-- 调度器,并把Trigger注册到Scheduler --><bean id="scheduler" class="org.springframework.scheduling.quartz.SchedulerFactoryBean"><property name="triggers"><list><ref bean="trigger"/></list></property></bean>
一个cron表达式有至少6个(也可能7个)有空格分隔的时间元素。
CronTrigger配置完整格式为: [秒] [分] [小时] [日] [月] [周] [年]*表示所有值. 例如:在分的字段上设置 "*",表示每一分钟都会触发。? 表示不指定值。使用的场景为不需要关心当前设置这个字段的值。例如:要在每月的10号触发一个操作,但不关心是周几,所以需要周位置的那个字段设置为"?" 具体设置为 0 0 0 10 * ?- 表示区间。例如 在小时上设置 "10-12",表示 10,11,12点都会触发。, 表示指定多个值,例如在周字段上设置 "MON,WED,FRI" 表示周一,周三和周五触发/ 用于递增触发。如在秒上面设置"5/15" 表示从5秒开始,每增15秒触发(5,20,35,50)。
测试
//FactoryBean测试,FactoryBean quartz定时任框架测试,但在junit不支持多线程,所以看不到每三秒执行的效果,我//另在model层中写一个类MyJob.java,用了main方法@Testpublic void FactoryBeantest() {
// ConfigurableApplicationContext ct = new ClassPathXmlApplicationContext("factoryBean.xml");
// Car baomaCar = (Car) ct.getBean("bwm");
// System.out.println(baomaCar);ConfigurableApplicationContext ct = new ClassPathXmlApplicationContext("factoryBean.xml");SchedulerFactoryBean scheduler=(SchedulerFactoryBean)ct.getBean("scheduler");scheduler.start();}
MyJobTest.java—model层中(无所谓那层了)
public class MyJobTest {public static void main(String[] args) {ConfigurableApplicationContext ct = new ClassPathXmlApplicationContext("factoryBean.xml");SchedulerFactoryBean scheduler=(SchedulerFactoryBean)ct.getBean("scheduler");scheduler.start();}}
----------------------------------------------------------------------------------------------------------------
quartz我的具体的每次工作任务
quartz我的具体的每次工作任务
quartz我的具体的每次工作任务
。。。。。。。。。
注解配bean
Spring引入了注解,通过"@XXX"的方式,让注解与Java Bean紧密结合,既大大减少了配置文件的体积,又增加了Java Bean的可读性与内聚性。
Spring注解配置初始化对象(<bean>):
spring中使用注解配置对象前,要在配置文件中配置<context:component-scan >
标签告诉spring框架,配置了注解的类的位置配置文件applicationContext.xml:
<!--告诉sping,要创建的bean在springdemo包下及子包中所有类的bean-->
<context:component-scan base-package="cn.ybzy.springdemo">
</context:component-scan>
注解说明:
Component是最初spring框架设计的,后来为了标识不同代码层,衍生出Controller,Service,Repository三个注解 作用相当于配置文件的bean标签,被注解的类,spring始化时,就会创建该对象
@Component("user") 给类注解
@Service("user") // service层
@Controller("user") // web业务层
@Repository("user")//dao层
@Scope(scopeName="singleton") 等同于配置文件的scope属性@Value(value="188") //给值属性赋值,可以用在方法上或者属性上
@Resource(name="car") //给对象赋值,该值car必须要已经声明(在配置文件中已经配置,或者在类对应中已经注解)
@PostConstruct //指定该方法在对象被创建后马上调用 相当于配置文件中的init-method属性
@PreDestroy //指定该方法在对象销毁之前调用 相当于配置文件中的destory-method属性
@Autowired 用的非常多//自动装配对象赋值@Qualifier("car2") 一起使用 告诉spring容器自动装配哪个对象
例:Tiger.java,Monkey.java,Zoo.java,zhujieBean.xml,RunTest.java
@Component("tiger")
public class Tiger {@Value(value="东南虎")private String name;public String getName() {return name;}public void setName(String name) {this.name = name;}@Overridepublic String toString() {return "Tiger [name=" + name + "]";}
}
@Component("monkey")
public class Monkey {@Value("金丝猴")private String name;public String getName() {return name;}public void setName(String name) {this.name = name;}@Overridepublic String toString() {return "Monkey [name=" + name + "]";}}
@Component
public class Zoo {@Resource(name="tiger")private Tiger tiger;@Resource(type=Monkey.class)private Monkey monkey;public Tiger getTiger() {return tiger;}public void setTiger(Tiger tiger) {this.tiger = tiger;}public Monkey getMonkey() {return monkey;}public void setMonkey(Monkey monkey) {this.monkey = monkey;}@Overridepublic String toString() {return "Zoo [tiger=" + tiger.getName() + ", monkey=" + monkey.getName() + "]";}}
<!-- 注解配bean --><!-- 1.先非注解配bean(对象),让我们作个比较 --><!-- <bean name="tiger" class="cn.ybzy.springdemo.model.Tiger" p:name="东南虎"></bean><bean name="monkey" class="cn.ybzy.springdemo.model.Monkey" p:name="金丝猴"></bean><bean name="nanchangzoo" class="cn.ybzy.springdemo.model.Zoo" p:monkey-ref="monkey" p:tiger-ref="tiger"></bean> --><!-- 2.注解配bean(对象),让我们作个比较 --><context:component-scan base-package="cn.ybzy.springdemo.model"></context:component-scan>
测试
//注解配bean测试@Testpublic void zhujieBeantest() {ApplicationContext ct = new ClassPathXmlApplicationContext("zhujieBean.xml");Tiger tiger=(Tiger)ct.getBean("tiger");System.out.println(tiger);//Zoo zoo = (Zoo)ct.getBean("nanchangzoo");Zoo zoo = (Zoo)ct.getBean("zoo");System.out.println(zoo);}
----------------------------------------------------------------------------------------------------------------
Tiger [name=东南虎]
Zoo [tiger=东南虎, monkey=金丝猴]
说一下@Resource的装配顺序:
1、@Resource后面没有任何内容,默认通过name属性去匹配bean,找不到再按type去匹配
2、指定了name或者type则根据指定的类型去匹配bean
3、指定了name和type则根据指定的name和type去匹配bean,任何一个不匹配都将报错
@Autowired
@Autowired顾名思义,就是自动装配,其作用是为了消除代码Java代码里面的getter/setter与bean属性中的property,(如:Zoo,可以不用setTiger,setMonkey方法)。当然,getter看个人需求,如果私有属性需要对外提供的话,应当予以保留。
因此,引入@Autowired注解,不要忘记配置文件要写:
<context:component-scan base-package="cn.ybzy.springdemo">
</context:component-scan>
然后才是在JavaBean的属性上加注解:
如果属性找不到对应的对象我不想让Spring容器抛 出异常,而就是显示null,可以吗?可以的,就是将@Autowired注解的required属性设置为false 即可:
@Autowired接口注入
上面的比较简单,我们只是简单注入一个Java类,那么如果有一个接口,有多个实现,Bean里引用的是接口名,又该怎么做呢?比如有一个Car接口:
Car接口有两个实现类,Spring并不知道应当引用哪个实现类。这种情况通常有两个解决办法:
- 删除其中一个实现类,Spring会自动去base-package下寻找Car接口的实现类,发现Car接口只有一个实现类,便会直接引用这个实现类
- 实现类就是有多个该怎么办?此时可以使用@Qualifier注解,指明你要spring装载那个对象:
最后提一下,还有一个功能和@Autowired差不多的一个注解@inject,它是jsr330规范的注解,用它的话要导入相应的jar包,我们推荐使用@Autowired
<dependency><groupId>javax.inject</groupId><artifactId>javax.inject</artifactId><version>1</version>
</dependency>
component-scan标签详解
<context:component-scan base-package="cn.ybzy.springdemo"/>
首先,这标签是需要context的命名空间的,在xxx.xml配置文件中------Namespace选项卡—Context http://…。
base-package
: 指定spring扫描注解的类所在的包。当需要扫描多个包的时候,可以使用逗号分隔。
如果只希望扫描特定的类,不是扫描包里的所有类的时候,可以使用resource-pattern
属性来指定只扫描的包。
这样配置,除了User的对象,其他都找不到了!
子标签
<context:exclude-filter type="annotation" expression=""/>
配置不扫描的类,可以有很多个这样的子标签。
这样配置,@controller注解的类的对象就找不到了!
子标签
<context:include-filter type="annotation" expression=""/>
配置要扫描的类,也可以有多个。
除了包含的注解类Controller以外的注解的类的对象都找不到了!
上面都是用的type=annotation,下面在看一下assignable
排除UserDao这个接口以及这个接口的实现类!include-file类似就不演示了!
泛型的依赖注入
spring4版本后,支持泛型自动注入,泛型类,不用我们用@Autowired或 <bean id=“xxx”…>由IOC来创建对象。
泛型依赖注入就是允许我们在使用spring进行依赖注入的同时,利用泛型的优点对代码进行精简,将可重复使用的代码全部放到一个类之中,方便以后的维护和修改。同时在不增加代码的情况下增加代码的复用性。
例:没用到泛型注入的代码,先列出来,好让我好好对比下面的泛型注入方式,看看那个会更精简代码
0.zhujieBean.xml----context命名空间,beans命名空间要加上
<?xml version="1.0" encoding="UTF-8"?>
<beans ......><context:component-scan base-package="cn.ybzy.springdemo"></context:component-scan>
</beans>
1.User,UserDao,UserDaoImpl,UserService,UserServiceImpl
public class User {private int id;private String username;private String password;private Map<String,String> map=new HashMap<String, String>();//get/set/无参构造方法/toString()
}
----------------------------------------------------------------------------------------------------------------
public interface UserDao {public void add(User user);}
----------------------------------------------------------------------------------------------------------------@Repository("userDao")
public class UserDaoImpl implements UserDao{@Overridepublic void add(User user) {System.out.println("userDao的add方法被调用了");System.out.println("user:"+user);}}
----------------------------------------------------------------------------------------------------------------
public interface UserService {public void add(User user);}----------------------------------------------------------------------------------------------------------------
@Service("userService")
public class UserServiceImpl implements UserService{public void add(User user) {userDao.add(user);}}
2.Authority,AuthorityDao,AuthorityDaoImpl,AuthorityService,AuthorityServiceImpl
public class Authority {private int id;private String authorityname;//get/set/无参构造方法/toString()
}
------------------------------------------------------------------------public interface AuthorityDao {public void add(Authority authority);
}
----------------------------------------------------------------------------------------------------------------@Repository("authorityDao")
public class AuthorityDaoImpl implements AuthorityDao{@Overridepublic void add(Authority authority) {System.out.println("AuthorityDaoImpl里的add方法");}}
----------------------------------------------------------------------------------------------------------------
public interface AuthorityService {public void add(Authority authority);}----------------------------------------------------------------------------------------------------------------
@Service("authorityService")
public class AuthorityServiceImpl implements AuthorityService{@Autowiredprivate AuthorityDao authorityDao;@Overridepublic void add(Authority authority) {authorityDao.add(authority);}}
3.RunTest.java
@Testpublic void zhujieBeantest() {ApplicationContext ct = new ClassPathXmlApplicationContext("zhujieBean.xml");//泛型依赖注入测试Map<String,String> map=new HashMap<>();map.put("xiong", "shwowen");User user=new User();Authority authority=new Authority();authority.setAuthorityname("open");authority.setId(2);user.setId(2);user.setUsername("xiongshaowen");user.setPassword("xiong");user.setMap(map);UserService userService=(UserService)ct.getBean("userService");userService.add(user);AuthorityService authorityService=(AuthorityService)ct.getBean("authorityService");authorityService.add(authority);}
-----------------------------------------------------------------------
userDao的add方法被调用了
user:User [id=2, username=xiongshaowen, password=xiong, map={xiong=shwowen}]
AuthorityDaoImpl里的add方法
例:改进上面的例子,我们编写两个泛型类,里面的代码以后就可以复用
BaseDao<T>
public class BaseDao<T>{public void add(T t) {System.out.println("BaseDao里的add方法,当然了,子类可重写,重写了,那怕没有输出,也会输出我哦,注意哦!");System.out.println("替代的t对象:"+t.toString());}
}
BaseService<T>
public class BaseService<T> {@Autowired //自动装备,IOC容器一启动就自动创建了它,不用我们用注解,或xml文件来指明public BaseDao<T> baseDao;}
1.User,UserDao,UserDaoImpl,UserService,UserServiceImpl
public class User {private int id;private String username;private String password;private Map<String,String> map=new HashMap<String, String>();//get/set/无参构造方法/toString()
}
----------------------------------------------------------------------------------------------------------------
public interface UserDao {public void add(User user);}
----------------------------------------------------------------------------------------------------------------@Repository("userDao")
public class UserDaoImpl extends BaseDao<User> implements UserDao{}
----------------------------------------------------------------------------------------------------------------
public interface UserService {public void add(User user);}----------------------------------------------------------------------------------------------------------------
@Service("userService")
public class UserServiceImpl extends BaseService<User> implements UserService{public void add(User user) {baseDao.add(user);}
}
2.Authority,AuthorityDao,AuthorityDaoImpl,AuthorityService,AuthorityServiceImpl
public class Authority {private int id;private String authorityname;//get/set/无参构造方法/toString()
}
------------------------------------------------------------------------public interface AuthorityDao {public void add(Authority authority);
}
----------------------------------------------------------------------------------------------------------------@Repository("authorityDao")
public class AuthorityDaoImpl extends BaseDao<Authority> implements AuthorityDao{}
----------------------------------------------------------------------------------------------------------------
public interface AuthorityService {public void add(Authority authority);}
----------------------------------------------------------------------------------------------------------------
@Service("authorityService")
public class AuthorityServiceImpl extends BaseService<Authority> implements AuthorityService{@Overridepublic void add(Authority authority) {baseDao.add(authority);}}
3.RunTest.java
不变
BaseDao里的add方法,当然了,子类可重写,重写了,那怕没有输出,也会输出我哦,注意哦!
替代的t对象:User [id=2, username=xiongshaowen, password=xiong, map={xiong=shwowen}]
BaseDao里的add方法,当然了,子类可重写,重写了,那怕没有输出,也会输出我哦,注意哦!
替代的t对象:Authority [id=2, authorityname=open]
总结:在泛型类中定义经常要重复使用的功能代码,如获取,插入,修改数据库记录的功能代码。再通过大量要使用它们的子类,继承它,这样我们都不用在子类中再写代码了,如果这种类有很多的情况下,会大量节省代码。