Springday02 jabcTemplate、注解IOC创建对象、注解IOC注入、注解 IO生命周期、纯注解IOC、Spring-junit、AOP-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;
            }
        });
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

halulu.me

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值