Springday02 jabcTemplate注解IOC创建对象注解IOC注入注解 IO生命周期纯注解IOCSpring-junitAOP-JDK和CGLIB动态代理
Posted halulu.me
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Springday02 jabcTemplate注解IOC创建对象注解IOC注入注解 IO生命周期纯注解IOCSpring-junitAOP-JDK和CGLIB动态代理相关的知识,希望对你有一定的参考价值。
目录
jabcTemplate
public class JdbcTemplateTest {
/*
* 核心模板工具类:JdbcTemplate
* 作用:是spring框架提供的操作jdbc的工具类,很方便实现CURD操作
* 注意:与mybatis框架功能类似,但是没有mybatis功能强大
*
* 使用步骤:
* 1.实例JdbcTemplate
* 2.给JdbcTemplate设置连接池对象,方便根据连接池获取连接操作数据库
* 3.执行增删改查操作
* */
//实例JdbcTemplate
private JdbcTemplate jdbcTemplate = new JdbcTemplate();
//给JdbcTemplate设置连接池对象,方便根据连接池获取连接操作数据库
@Before //目的是在执行每个测试方法前,给jdbcTemplate设置连接池
public void before(){
DruidDataSource dataSource = new DruidDataSource();
dataSource.setUrl("jdbc:mysql:///springdb?charsetEncoding=utf8");
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
dataSource.setUsername("root");
dataSource.setPassword("root");
//设置到JdbcTemplate
jdbcTemplate.setDataSource(dataSource);
}
//查询1:查询账户表所有数据(查询多条记录)
@Test
public void test_select_all(){
//定义查询sql语句
String sql = "select * from account";
//查询多条数语法:jdbcTemplate.query(String sql,new BeanPropertyRowMapper<>(Class clazz),可变长度占位符参数);
// 参数1:String sql, 设置要执行查询的sql语句,里面可以设置占位符,符号"?"
// 参数2:new BeanPropertyRowMapper<>(Class clazz), 设置返回数据的类型对象,工具类会自动将数据库查询的结果封装层指定类对象返回
// 参数3:可变长度占位符参数,sql语句的占位符的对应值的设置
List<Account> accountList = jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(Account.class));
//打印
accountList.forEach(System.out::println);
}
//查询2:查询执行账户表中一条数据,根据主键查询
@Test
public void test_select_one(){
//定义查询sql语句
String sql = "select * from account where accountId = ?";
//查询多条数语法:jdbcTemplate.queryForObject(String sql,new BeanPropertyRowMapper<>(Class clazz),可变长度占位符参数);
// 参数1:String sql, 设置要执行查询的sql语句,里面可以设置占位符,符号"?"
// 参数2:new BeanPropertyRowMapper<>(Class clazz), 设置返回数据的类型对象,工具类会自动将数据库查询的结果封装层指定类对象返回
// 参数3:可变长度占位符参数,sql语句的占位符的对应值的设置
Account account = jdbcTemplate.queryForObject(sql, new BeanPropertyRowMapper<>(Account.class),4);
//这个注意:查不到会报异常,如果没有查询到1条数据会报异常
//打印
System.out.println(account);
}
//增
@Test
public void test_insert(){
//定义查询sql语句
String sql = "insert into account values(null,?,?)";
//增删改语法:jdbcTemplate.update(String sql,可变长度占位符参数);
// 参数1:sql,sql语句,sql语句中的占位符使用?,这里使用原始jdbc的sql语句,注意不是 #{}
// 参数2:可变长度占位符参数, 用于设置sql语句中占位符的值,这是可变长度
int row = jdbcTemplate.update(sql, 46, 3000);
//打印
System.out.println("影响行数:"+row);
}
//改
@Test
public void test_update(){
//定义查询sql语句
String sql = "update account set uid=? , money=? where accountId = ?";
//增删改语法:jdbcTemplate.update(String sql,可变长度占位符参数);
// 参数1:sql,sql语句,sql语句中的占位符使用?,这里使用原始jdbc的sql语句,注意不是 #{}
// 参数2:可变长度占位符参数, 用于设置sql语句中占位符的值,这是可变长度
int row = jdbcTemplate.update(sql, 46, 4000,4);
//打印
System.out.println("影响行数:"+row);
}
//删除
@Test
public void test_delete(){
//定义查询sql语句
String sql = "delete from account where accountId = ?";
//增删改语法:jdbcTemplate.update(String sql,可变长度占位符参数);
// 参数1:sql,sql语句,sql语句中的占位符使用?,这里使用原始jdbc的sql语句,注意不是 #{}
// 参数2:可变长度占位符参数, 用于设置sql语句中占位符的值,这是可变长度
int row = jdbcTemplate.update(sql, 4);
//打印
System.out.println("影响行数:"+row);
}
}
注解IOC创建对象
<context:component-scan base-package="com.halulu"></context:component-scan>
进行包扫描时,会对配置的包及其子包中所有文件进行扫描
扫描过程是以文件夹递归迭代的形式进行的
扫描过程仅读取合法的java文件
扫描时仅读取spring可识别的注解
扫描结束后会将可识别的有效注解转化为spring对应的资源加入IoC容器
@Controller: 一般用于表现层web层的注解。 同@Component
@Service: 一般用于业务层service层的注解。 同@Component
@Repository: 一般用于持久层dao层的注解。 同@Component@Component: 除了上述情形以外的工具类,使用此注解。
<?xml version="1.0" encoding="UTF-8"?>
<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.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="com.halulu"></context:component-scan>
</beans>
@Component
public class User {
public User() {
System.out.println("创建了User");
}
}
注解IOC注入
1、@Autowired修饰字段
@Autowired 先根据类型查找,类型匹配找到多个,再根据字段名(成员变量名)查找
@Component
public class User {
/*
* @Autowired
* 介绍: 自动装配,自动从IOC容器中获取数据注入
* 作用: 可以注入字段与set方法的数据
* 注入数据过程:
* 1.先从IOC容器中查找字段相同类型的对象数据注入
* 注意:如果找到多个类型相同的数据会报错
* 2.如果类型没有找到合适的,会根据字段名作为引用名进行查找注入
* 如果以上2个步骤都不到,就会报错
*
* 依赖注入数据常见错误
* 错误1: expected at least 1 bean which qualifies as autowire candidate.
* 一个都找不到,无法注入,会报错
* 错误2: expected single matching bean but found 2: str1,str2
* 找到多个类型匹配,springIOC不知道注入哪个,会报错
*
* 使用方式
* 方式1[推荐]: @Autowired 先根据类型查找,类型匹配找到多个,再根据字段名注入
* 方式2[了解]: @Autowired(required = false) 找到就注入,找不到就不注入,默认值为null
*
* */
@Autowired
private String name;
@Override
public String toString() {
return "User3{" +
"name='" + name + '\\'' +
'}';
}
}
<bean class="java.lang.String" id="str" >
<constructor-arg value="张三"></constructor-arg>
</bean>
<bean class="java.lang.String" id="str2" >
<constructor-arg value="李四"></constructor-arg>
</bean>
<bean class="java.lang.String" id="name" >
<constructor-arg value="王五"></constructor-arg>
</bean>
2、@Autowired修饰成员方法
@Component
public class User4 {
private String name;
/*
* 目标:使用@Autowired给类的set方法注入数据
* @Autowired 注入方法数据的过程
* 1.先根据方法参数类型注入
* 2.如果找到类型有多个,再根据参数名作为引用名注入
* */
@Autowired
public void setName(String name123) {
this.name = name123;
}
}
<!--定义字符串类型4-->
<bean id="name123" class="java.lang.String">
<constructor-arg value="狗娃"></constructor-arg>
</bean>
3、@Qualifier起别名
@Component
public class User5 {
/*
* 目标:使用@Qualifier设置自定义别名(引用名)注入数据
* @Qualifier
* 介绍: 可以自定义别名注入
* 作用: 与@Autowired一起使用实现自定义别名注入, 弥补了@Autowired的缺点
* 并且当@Qualifier修饰方法参数时也可以单独使用,后面案例中讲解
* */
@Autowired
@Qualifier("name123")
private String name;
}
4、@Resource(JDK9之后被淘汰)
在jdk1.9及以后版本不提供支持,不推荐使用
@Resource = @Autowred + @Qualifier
@Component
public class User6 {
/*
* 目标:使用@Resource注入数据
* @Resource
* 介绍: jdk提供的注解,但是jdk9及以后版本就淘汰了,不推荐使用
* 作用: spring框架在@Resource注解至上键增加了功能,实现注入数据
* @Resource = @Autowired + @Qualifier
* 可以实现先根据类型,再根据自定义别名注入
* */
@Resource(name = "name123")
private String name;
}
5、@Value设置默认值
@Component
@PropertySource("classpath:jdbc.properties") //加载外部类路径的配置文件
public class User7 {
/*
* 目标:使用@Value注入数据
* @Value
* 作用:用于设置默认值,从IOC容器中获取、配置文件中获取、直接赋值、执行SpringEL
* 格式1:直接赋值 @Value("丫蛋") 功能与直接给字段赋值一样,例如:name="丫蛋"
* 格式2:使用springEL表达式 @Value("#{T(java.lang.Math).PI}")
* 格式3:读取配置文件jdbc.properties中有:jdbc.url=xxxxx
* 读取配置文件注解:@PropertySource("classpath:jdbc.properties")
* 使用@Value("${jdbc.url}") 修饰字段读取数据注入
* */
//@Value("丫蛋") 与private String name=“丫蛋”;
@Value("丫蛋")
private String name;
@Value("#{T(java.lang.Math).PI}")
private Integer num;
@Value("${jdbc.url}")
private String url;
}
注解 IOC:对象范围与生命周期相关注解
@Scope 【对象范围】
@PostConstruct 【修饰初始化方法,创建对象之后执行】
@PreDestroy 【修饰回收资源方法,销毁容器之前执行】
@Lazy 【延迟初始化
与Xml方式对比
<bean id="" class="" 对应的注解:@Controller、@Servvice、@Repository、@Component
scope="" 使用@Scope注解取代
init-method="" 使用@PostConstruct注解取代
destroy-method="" 使用@PreDestroy注解取代
lazy-init="" 使用@Lazy注解取代
/>
纯注解IOC
BeanConfig
/**
* 目标:使用纯注解当前类代替applicationContext.xml配置文件
*
*/
@Configuration
@ComponentScan(basePackages = "com.halulu")
@Import(JdbcConfig.class)
public class BeansConfig {
}
JdbcConfig
/**
* 目标:加载关于数据库配置的信息
*
* @PropertySource("classpath:jdbc.properties")
* 作用:加载类路径的配置文件jdbc.properties
*/
@PropertySource("jdbc.properties")
public class JdbcConfig {
@Value("${jdbc.url}")
private String url;
@Value("${jdbc.driver}")
private String driver;
@Value("${jdbc.username}")
private String username;
@Value("${jdbc.password}")
private String password;
//创建DruidDataSource对象并加入IOC容器
//@Bean作用:将方法的返回值对象加入IOC容器
// 格式1:@Bean 默认对象别名是类名首字母小写,这里id="dataSource"
// 格式2:@Bean("指定别名")
@Bean("dataSource1")
public DataSource createDruidDataSource(){
DruidDataSource dataSource = new DruidDataSource();
dataSource.setUrl(this.url);
dataSource.setDriverClassName(this.driver);
dataSource.setPassword(this.password);
dataSource.setUsername(this.username);
return dataSource;
}
@Bean
//使用@Bean 的方法参数对象数据会自动从IOC容器中查找并注入
//@Qualifier("dataSource1")可以找dataSource1
public JdbcTemplate createJdbcTemplate(@Qualifier("dataSource1") DataSource dataSource){
return new JdbcTemplate(dataSource);
}
}
Spring-junit
Spring整合Junit, 主要是为了简化测试而已。
使用注解自动创建全局 IOC 容器对象,代替每个测试方法重复创建IOC容器代码
<!--
spring整合junit包:spring-tes
注意:使用这个整个包,要求依赖的junit的包必须是4.12及版本以上
-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.1.8.RELEASE</version>
</dependency>
纯注解开发,Spring整合Junit测试:
/**
* 目标:使用spring整合junit进行单元测试
* 优势:简化了硬编码创建IOC容器与获取对象注入
*/
@RunWith(SpringJUnit4ClassRunner.class) //设置启动测试类,目的先走spring的测试类
@ContextConfiguration(classes=SpringConfiguration.class ) //根据配置注解类创建IOC容器,classes不能省略
public class AppTest2 {
@Autowired
private AccountService accountService;
@Test
public void test(){
//3.调用业务方法测试
List<Account> accountList = accountService.findAll();
//4.遍历输出
accountList.forEach(System.out::println);
}
}
XML开发,Spring整合Junit测试:
/**
* 目标:使用spring整合junit进行单元测试
* 优势:简化了硬编码创建IOC容器与获取对象注入
*/
@RunWith(SpringJUnit4ClassRunner.class) //设置启动测试类,目的先走spring的测试类
//根据配置文件applicationContext.xml创建IOC容器,locations可以省略,classpath不能省略
@ContextConfiguration(locations = "classpath:applicationContext.xml")
public class AppTest3 {
@Autowired
private AccountService accountService;
@Test
public void test(){
//3.调用业务方法测试
List<Account> accountList = accountService.findAll();
//4.遍历输出
accountList.forEach(System.out::println);
}
}
AOP—JDK接口动态代理
public class ProxyFactroyByJDK {
//使用jdk动态代理增强目标对象,实现日志记录功能
public static Object getProxy(Object target){
//对目标对象增强返回代理对象
return Proxy.newProxyInstance(
target.getClass().getClassLoader(), //目标对象的类加载器
target.getClass().getInterfaces(), //目标对象实现的接口类型
(proxy,method,args)->{ //事件处理程序,执行代理方法的时候触发运行
//proxy:目标对象增强后的代理对象
//method:目标对象的方法
//args:目标对象的方法参数列表
//增强1:输出日志之前
System.out.println("日志之前");
//执行目标的方法
Object result = method.invoke(target, args);
//增强2:输出日志之后
System.out.println("日志之后");
return result;
}
);
}
}
AOP—CGLIB普通类动态代理
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>5.1.8.RELEASE</version>
</dependency>
public class ProxyFactoryByCglib {
//目标:使用cglib动态代理对目标增强(对普通类增强的代理,类不需要实现接口)
//cglib增强的本质:是通过给目标的类创建一个动态的子类实现增强,本质通过继承实现增强
public static Object getProxy(Object target){
/**
* cglib创建代理对象语法:
* Enhancer.create(Class clazz,Callback callback);
* 参数1: clazz 目标对象的字节码对象
* 参数2: callback 类似jdk动态代理的事件处理程序,用于编写增强
*
* Callback是一个接口, 有实现类子接口 MethodInterceptor, 实现拦截代理对象的方法进行增强
* 由于allback 不是函数式接口,所以不可以写lambda表达式
*
* enhancer 译为 “增强者”
*/
return Enhancer.create(target.getClass(), new MethodInterceptor() {
@Override
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
//参数1:Object proxy: 生成的代理对象
//参数2: Method method: 目标对象的方法
//参数3: Object[] args: 目标对象方法参数数组对象
//参数4: MethodProxy methodProxy: 代理对象的方法,基本不需要操作
//增强1:输出日志
System.out.println("日志之前");
//执行目标方法
Object result = method.invoke(target, args);
//增强2:输出日志
System.out.println("日志之后");
return result;
}
});
}
}
以上是关于Springday02 jabcTemplate注解IOC创建对象注解IOC注入注解 IO生命周期纯注解IOCSpring-junitAOP-JDK和CGLIB动态代理的主要内容,如果未能解决你的问题,请参考以下文章
Springday01 maven依赖Spring介绍IOC模块IOC控制反转DI依赖注入SpEL表达式
Springday05 SpringMVC访问静态资源操作请求域控制器方法返回值JSON数据交互RESTful风格文件上传异常处理拦截器
Springday04 SpringMVC入门案例控制器和三大主件Spring请求参数绑定SpringMVC使用servlet的api请求头请求体相关注解