IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> 跟着江南一点雨学习spring(4) -> 正文阅读

[Java知识库]跟着江南一点雨学习spring(4)

? ? ? ? 之前我们学习了spring中的IOC,IOC的底层原理就是反射,今天学习spring中的AOP,AOP的底层原理就是动态代理,首先我们要知道java中的代理都有哪些?

? ? ? ? java的代理有静态代理和动态代理,静态代理就是一种设计模式,这里就不过多介绍。什么是动态代理呢,动态代理就是在内存从动态的生成一个接口的实现类或者一个类 的子类 。

????????分别有两种方式进行动态代理,一种是JDK 自带的,不用额外的添加依赖,但只能动态代理接口类型的,另一种是CGLIB提供的动态代理,需要额外的添加cglib的依赖,可以动态代理接口和类。下面就分别演示两种方法的实现。 代理测试方法执行的时间

? ? ? ? JDK的

接口

package com.qfedu.demo.jdk;

public interface JiSuanQi {
    int add(int a,int b);
    int mines(int a,int b);
}

实现类

package com.qfedu.demo.jdk;

public class JiSuanQiImpl implements JiSuanQi {
    @Override
    public int add(int a, int b) {
        int c = a+b;
        System.out.println(c);
        return c;
    }

    @Override
    public int mines(int a, int b) {
        int c = a-b;
        System.out.println(c);
        return c;
    }
}

测试

package com.qfedu.demo.jdk;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
 * JDK 动态代理,实际上就是动态的给 Calculator 这个接口生成一个实现类.
 *
 * JDK 动态代理,只能代理接口,对于没有接口的类,是无法使用 JDK 动态代理的
 *
 * <p>
 * public class A implements Calculator{
 * CalculatorImpl impl = new CalculatorImpl();
 * int add(int a,int b){
 * //记录开始时间
 * int a = impl.add(a,b);
 * //记录结束时间
 * //打印执行耗时
 * //返回 a
 * <p>
 * }
 * }
 */
public class Demo1 {
    public static void main(String[] args) {
        ClassLoader loder = Demo1.class.getClassLoader();
        Class<?>[] interfaces = {JiSuanQi.class};
        InvocationHandler handler = new InvocationHandler() {
            /**
             *
             * @param o 这个是具体的代理对象
             * @param method 这个是代理的方法
             * @param objects 代理的方法的参数
             * @return
             * @throws Throwable
             */
            @Override
            public Object invoke(Object o, Method method, Object[] objects) throws Throwable {
                long l = System.currentTimeMillis();
                Object invoke = method.invoke(new JiSuanQiImpl(), objects);
                long l1 = System.currentTimeMillis();
                System.out.println("该方法耗费毫秒值为"+(l1-l));
                return invoke;
            }
        };
        //调用这个方法获取一个动态代理对象
        //1. 类加载器
        //2. 生成的动态代理对象所实现的接口
        //3. 动态代理对象具体的处理逻辑
        JiSuanQi o = (JiSuanQi) Proxy.newProxyInstance(loder, interfaces, handler); //这个返回对象就是上面的o
        o.add(2,1); //这里是有返回值的 但这个返回值是上面的invoke 

    }

}

以上就是JDK的动态代理

CGLIB的动态代理

首先引入依赖

 <dependencies>
        <dependency>
            <groupId>cglib</groupId>
            <artifactId>cglib</artifactId>
            <version>3.3.0</version>
        </dependency>
    </dependencies>

?然后创建父类

package com.qfedu.demo.cglib;

public class JiSuanQi {
    public int add(int a, int b) {
        int c = a+b;
        System.out.println(c);
        return c;
    }

    public int mines(int a, int b) {
        int c = a-b;
        System.out.println(c);
        return c;
    }
}

再创建一个拦截器

package com.qfedu.demo.cglib;

import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;
/**
 * 首先定义一个计算器的拦截器
 * <p>
 * 这是一个方法的拦截器,即将来执行计算器的方法时候,会被自动拦截下来。
 */
public class JiSuanQiInterceptor implements MethodInterceptor {
    /**
     * 这个方法类似于 JDK 动态代理中的 invoke 方法,要额外加进来的代码,就放在这个里边
     *
     * @param o           代理对象  不可以直接调用method中的方法 所以cglib增加了一个methodProxy参数, 代理对象就可以通过这个参数调用方法
     * @param method      代理的方法  这个不可以放代理对象  要放的是实现类的对象 和参数
     * @param objects     方法的参数
     * @param methodProxy 方法代理对象  里面的放的就是代理对象 和参数
     * @return
     * @throws Throwable
     */
    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        long l = System.currentTimeMillis();
        //调用父类中的方法,父类就是 CalculatorImpl,子类是一个动态生成的类
        //调用父类的方法,就完成了真正的计算器方法的调用
        //Object o1 = methodProxy.invokeSuper(o, objects);
        //调用接口的方法
        Object invoke = method.invoke(new Ji1Impl(), objects);
        long l1 = System.currentTimeMillis();
        System.out.println("该方法耗费毫秒值为"+(l1-l));
        return invoke;
    }
}

测试类

package com.qfedu.demo.cglib;

import net.sf.cglib.proxy.Enhancer;

public class Demo {
    public static void main(String[] args) {
        //创建字节增强器
        Enhancer enhancer = new Enhancer();
        //设置父类
        //enhancer.setSuperclass(JiSuanQi.class);
        //设置回调 即设置方法拦截器
        enhancer.setCallback(new JiSuanQiInterceptor());
        //这里拿到的,并不是 JiSuanQi 这个类的对象本身,而是他的子类的一个对象
        JiSuanQi jiSuanQi = (JiSuanQi) enhancer.create();
        jiSuanQi.mines(2,1);

        //设置接口
        Class<?>[] interfaces = {Ji1.class};
        enhancer.setInterfaces(interfaces);
        Ji1 ji1 = (Ji1) enhancer.create();
        ji1.add(2,2);

    }
}

以上就是java的两种动态代理,spring的AOP的底层原理就是使用这两种动态代理的,默认接口使用JDK的,类的使用CGLIB的

? ? ? ? 那么在spring容器中要怎么设置动态代理呢,我们可以通过xml配置文件来设置,也可以通过java配置类来设置。

? ? ? ? 先以xml配置文件来配置

先导入依赖

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.qfedu</groupId>
    <artifactId>aop_xml</artifactId>
    <version>1.0-SNAPSHOT</version>
    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.3.22</version>
        </dependency>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.9.9.1</version>
        </dependency>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjrt</artifactId>
            <version>1.9.9.1</version>
        </dependency>
    </dependencies>


</project>

和刚才一样创建一个接口和实现类

package com.qfedu.demo.service;

import com.qfedu.demo.MyAction;
@MyAction
public class JiSuanQiImpl implements JiSuanQi {


    @Override
    public int add(int a, int b) {
        System.out.println(a+b);
        return a+b;
    }

    @Override
    public void mine(int a, int b) {
//        int s =1/0;
        System.out.println(a-b);
    }
}
package com.qfedu.demo.service;

public interface JiSuanQi {
    int add(int a,int b);
    void mine(int a,int b);
}

然后创建通知类 通知类里面就是编写你要做的事情的代码

package com.qfedu.demo.aop;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;

/**
 * AOP 面向切面编程
 * <p>
 * 1. 切点(PointCut):要添加的代码的位置,就是切点
 * 2. 增强/通知(Advice):要添加的代码
 * 3. 切面(Aspect): 切点+通知
 * <p>
 * 在 Spring AOP 中,有五种不同类型的 Advice:
 * 1. 前置通知:目标方法执行之前会执行
 * 2. 后置通知:目标方法执行之后会执行
 * 3. 异常通知:目标方法抛出异常的时候会触发
 * 4. 返回通知:目标方法返回值的时候会触发
 * 5. 环绕通知:前四个之和。
 */
public class LogAdvice {
    //前置通知 名字随意
    public void before(JoinPoint jp){
        //获取被拦截下来的方法名称
        String name = jp.getSignature().getName();
        System.out.println(name+"开始执行了");
    }
    //后置通知
    public void after(JoinPoint jp){
        //获取被拦截下来的方法名称
        String name = jp.getSignature().getName();
        System.out.println(name+"执行结束了");
    }
    //异常通知
    public void ex(JoinPoint jp,Exception e){
        String name = jp.getSignature().getName();
        System.out.println(name+"方法抛出了"+e.getMessage()+"异常");
    }
    //返回值通知
    public void afterReturning(JoinPoint jp,Object r){
        String name = jp.getSignature().getName();
        System.out.println(name+"方法的返回值是"+r);
    }

    //环绕通知
    public Object around(ProceedingJoinPoint point){
        String name = point.getSignature().getName();
        try {

            //前置通知
            System.out.println(name+"方法执行了。。。");
            //这个方法就相当于是JDK动态代理中的  Object o = method.invoke(o,objects)
            Object proceed = point.proceed();
            //后置通知
            System.out.println(name+"方法结束了....");
            //返回值通知
            System.out.println(name+"返回值为"+proceed);
            return proceed;
        } catch (Throwable throwable) {
            throwable.printStackTrace();
            //异常通知
            System.out.println(name+"方法抛出了"+throwable.getMessage()+"异常");
        }
        return null;
    }
}

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" xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd">

<!--   1 这里先要配置一个实现类的bean-->
    <bean class="com.qfedu.demo.service.JiSuanQiImpl" id="jiSuanQi"/>
<!--    开始配置AOP-->
<!--  2  配置通知bean-->
    <bean id="logAdvice" class="com.qfedu.demo.aop.LogAdvice"/>
<!--    spring的aop默认情况下是有接口的就调用jdk的动态代理,没有接口调用的是cglib的动态代理 要是想都用cglib的动态代理 只需要在
            aop:config标签里将proxy-target-class属性该为true即可
        3    -->
    <aop:config proxy-target-class="true">
        <!--这个地方用来配置切点
       第一个 int 表示方法的返回值
       接下来是方法的全路径
       最后还要指定方法的参数类型(防止方法有重载)
       -->
<!--  4.1      <aop:pointcut id="pc1" expression="execution(int com.qfedu.demo.service.JiSuanQiImpl.add(int,int))"/>-->
        <!--
        这里是拦截一个包下所有类的所有方法
       第一个 * 表示返回值任意
       第二个 * 表示 service 包下的所有类
       第三个 * 表示方法名任意
       .. 表示参数任意:类型任意、个数任意
       -->
<!--    4.2    <aop:pointcut id="pc1" expression="execution(* com.qfedu.demo.service.*.*(..))"/>-->
<!--        当注解在方法上时-->
<!--     4.3   <aop:pointcut id="pc1" expression="@annotation(com.qfedu.demo.MyAction)"/>-->
<!--    4.5    当注解在类上时-->
        <aop:pointcut id="pc1" expression="@within(com.qfedu.demo.MyAction)"/>
        <!--
        这个地方是配置切面的地方,切面=切点+通知
     5   -->
        <aop:aspect ref="logAdvice">
            <!--
            aop:before 这个节点用来配置前置通知,method 指的是前置通知的方法名称,pointcut-ref 指的是引用的切点
           6 -->

           <!-- <aop:before method="before" pointcut-ref="pc1"/> 前置通知
            <aop:after method="after" pointcut-ref="pc1"/>后置通知
            <aop:after-returning method="afterReturning" pointcut-ref="pc1" returning="r"/> 返回值通知
            <aop:after-throwing method="ex" pointcut-ref="pc1" throwing="e"/> 异常通知-->
            <aop:around method="around" pointcut-ref="pc1" /> 环绕通知 四合一
        </aop:aspect>

    </aop:config>
</beans>

这样就可以测试了

import com.qfedu.demo.service.JiSuanQi;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Demo1 {
    /**
     * Spring 中,如果被代理的对象有接口,则默认使用 JDK 动态代理
     * 如果被代理的对象没有接口,则默认使用 CGLIB 动态代理
     */
    public static void main(String[] args) {
        ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
        //这里获取到的不是JiSuanQiImpl注入spring容器的对象 而是通aop代理动态生成的JiSuanQi接口的一个实现类的对象
        JiSuanQi jiSuanQi = (JiSuanQi) ctx.getBean("jiSuanQi");
        jiSuanQi.add(2,2);
        jiSuanQi.mine(2,2);
    }
}

java配置类进行设置

首先就是依赖和接口与实现类都要有,这里就不重新写了

然后就是java配置类,很简单就是使用注释进行包扫描

package com.qfedu.demo.config;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration
@ComponentScan(basePackages = "com.qfedu.demo")
public class JavaConfig {
}

然后就是 切面类

package com.qfedu.demo.aop;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.stereotype.Component;

@Component
//表示开启aop自动代理功能
//这个注解就类似于在 XML 文件中配置的 aop:config
@EnableAspectJAutoProxy(proxyTargetClass = true)
//表示当前类是一个切面,意味着这个类中既有切点,又有通知
@Aspect
public class LogAdvice {
    //定义一个方法表示切点
    @Pointcut("execution(* com.qfedu.demo.service.*.*(..))")
    public void pc(){

    }
    //前置通知 名字随意
    @Before("pc()")
    public void before(JoinPoint jp){
        //获取被拦截下来的方法名称
        String name = jp.getSignature().getName();
        System.out.println(name+"开始执行了");
    }
    //后置通知
    @After("pc()")
    public void after(JoinPoint jp){
        //获取被拦截下来的方法名称
        String name = jp.getSignature().getName();
        System.out.println(name+"执行结束了");
    }
    //异常通知
    @AfterThrowing(value = "pc()",throwing = "e")
    public void ex(JoinPoint jp,Exception e){
        String name = jp.getSignature().getName();
        System.out.println(name+"方法抛出了"+e.getMessage()+"异常");
    }
    //返回值通知
    @AfterReturning(value = "pc()",returning = "r")
    public void afterReturning(JoinPoint jp,Object r){
        String name = jp.getSignature().getName();
        System.out.println(name+"方法的返回值是"+r);
    }

    //环绕通知
    @Around("pc()")
    public Object around(ProceedingJoinPoint point){
        String name = point.getSignature().getName();
        try {

            //前置通知
            System.out.println(name+"方法执行了。。。");
            //这个方法就相当于是JDK动态代理中的  Object o = method.invoke(o,objects)
            Object proceed = point.proceed();
            //后置通知
            System.out.println(name+"方法结束了....");
            //返回值通知
            System.out.println(name+"返回值为"+proceed);
            return proceed;
        } catch (Throwable throwable) {
            throwable.printStackTrace();
            //异常通知
            System.out.println(name+"方法抛出了"+throwable.getMessage()+"异常");
        }
        return null;
    }
}

这样就写完了,然后就可以测试了

import com.qfedu.demo.config.JavaConfig;
import com.qfedu.demo.service.JiSuanQi;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class Demo1 {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(JavaConfig.class);
        JiSuanQi j = (JiSuanQi) ctx.getBean(JiSuanQi.class);
        j.add(2,2);
    }
}

以上就是spring的AOP的动态代理了

最后再来一个jdbcTemplate的使用方法

先引入依赖

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.qfedu</groupId>
    <artifactId>jdbcTempulac</artifactId>
    <version>1.0-SNAPSHOT</version>
    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.3.22</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>5.3.22</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.2.11</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.30</version>
        </dependency>

    </dependencies>


</project>

db.properties配置文件

# druid.properties文件的配置
db.driverClassName=com.mysql.cj.jdbc.Driver
db.url=jdbc:mysql://localhost:3306/day09
db.username=root
db.password=123456
# 初始化连接数量
db.initialSize=5
# 最大连接数
db.maxActive=10
# 最大超时时间
db.maxWait=3000

?

xml方式:

? ? ? ? 实体类

package com.qfedu.demo.p1.entity;

public class User {
    private Integer uid;
    private String uname;
    private String upwd;

    @Override
    public String toString() {
        return "User{" +
                "uid=" + uid +
                ", uname='" + uname + '\'' +
                ", upwd='" + upwd + '\'' +
                '}';
    }

    public Integer getUid() {
        return uid;
    }

    public void setUid(Integer uid) {
        this.uid = uid;
    }

    public String getUname() {
        return uname;
    }

    public void setUname(String uname) {
        this.uname = uname;
    }

    public String getUpwd() {
        return upwd;
    }

    public void setUpwd(String upwd) {
        this.upwd = upwd;
    }
}

? ? ? ? dao类

package com.qfedu.demo.p1.dao;

import com.qfedu.demo.p1.entity.User;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;

public class UserDao {
    private JdbcTemplate jdbcTemplate;

    public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
        this.jdbcTemplate = jdbcTemplate;
    }

    public User getUserByUName(String uname){
        User user = jdbcTemplate.queryForObject("select * from user where uname=?", new BeanPropertyRowMapper<>(User.class), uname);
        return user;
    }
}

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

<!--第一步,引入db.properties配置文件-->
    <context:property-placeholder location="classpath:db.properties"/>
<!--    第二步 配置数据源-->
    <bean class="com.alibaba.druid.pool.DruidDataSource" id="dataSource">
        <property name="driverClassName" value="${db.driverClassName}"/>
        <property name="url" value="${db.url}"/>
        <property name="username" value="${db.username}"/>
        <property name="password" value="${db.password}"/>
    </bean>
<!--    第三步,配置JdbcTemplate-->
    <bean class="org.springframework.jdbc.core.JdbcTemplate" id="jdbcTemplate">
        <property name="dataSource" ref="dataSource"/>
    </bean>

    <bean class="com.qfedu.demo.p1.dao.UserDao" id="userDao">
        <property name="jdbcTemplate" ref="jdbcTemplate"/>
    </bean>

</beans>

最后测试

package com.qfedu.demo.p1;

import com.qfedu.demo.p1.dao.UserDao;
import com.qfedu.demo.p1.entity.User;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Demo1 {
    public static void main(String[] args) {
        ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
        UserDao userDao = ctx.getBean(UserDao.class);
        User user = userDao.getUserByUName("班长");
        System.out.println(user);
    }
}

下面是java配置类的方法

实体类是一样的?

dao类

package com.qfedu.demo.p2.dao;

import com.qfedu.demo.p2.entity.User;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;

import java.util.List;

public class UserDao {
    private JdbcTemplate jdbcTemplate;

    public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
        this.jdbcTemplate = jdbcTemplate;
    }

    public User getUserByUName(String uname){
        User user = jdbcTemplate.queryForObject("select * from user where uname=?", new BeanPropertyRowMapper<>(User.class), uname);
        return user;
    }

    public List<User> getAllUser(){
        return jdbcTemplate.query("select * from user",new BeanPropertyRowMapper<>(User.class));
    }
}

java配置类

package com.qfedu.demo.p2.config;

import com.alibaba.druid.pool.DruidDataSource;
import com.qfedu.demo.p2.dao.UserDao;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.jdbc.core.JdbcTemplate;

import javax.sql.DataSource;

@Configuration
//加载配置文件
@PropertySource("classpath:db.properties")
public class JavaConfig {
    //设置值
    @Value("${db.url}")
    String url;
    @Value("${db.username}")
    String username;
    @Value("${db.password}")
    String password;
    @Value("${db.driverClassName}")
    String driverClassName;

    //注册数据源bean
    @Bean
    DataSource dataSource(){
        DruidDataSource ds = new DruidDataSource();
        ds.setUrl(url);
        ds.setUsername(username);
        ds.setPassword(password);
        ds.setDriverClassName(driverClassName);
        return ds;
    }
    //注册JdbcTemplate的bean
    @Bean
    JdbcTemplate jdbcTemplate(){
        JdbcTemplate jdbcTemplate = new JdbcTemplate();
        jdbcTemplate.setDataSource(dataSource());
        return jdbcTemplate;
    }
    //注册UserDao的bean
    @Bean
    UserDao userDao(){
        UserDao userDao = new UserDao();
        userDao.setJdbcTemplate(jdbcTemplate());
        return userDao;
    }
}

测试类

package com.qfedu.demo.p2;

import com.qfedu.demo.p2.config.JavaConfig;
import com.qfedu.demo.p2.dao.UserDao;
import com.qfedu.demo.p2.entity.User;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

import java.util.List;

public class Demo2 {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(JavaConfig.class);
        UserDao userDao = ctx.getBean(UserDao.class);
        List<User> userList = userDao.getAllUser();
        for (User user : userList) {
            System.out.println(user);
        }
    }
}

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2022-09-24 20:42:44  更:2022-09-24 20:44:57 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 8:42:24-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码