Day_05 Spring

本文详细介绍了如何使用Spring框架操作数据库,包括引入依赖、定义DAO接口及其实现、配置Spring XML文件以及进行代码测试。接着探讨了IoC注解,如@Component、@Autowired、@Qualifier等,解释了它们的工作原理和应用场景。同时,讲解了基于注解的Spring配置,如@Configuration、@ComponentScan和@Bean。最后,提到了AOP的概念、动态代理(JDKProxy和CGLIB)以及AOP在Spring中的应用,包括通知、切入点和织入过程。

01-Spring操作数据库(掌握)

  • 需求

    • 查询用户列表
  • 技术体系

    • Spring + DbUtils + mysql + druid
  • 开发步骤

    • ①引入依赖
    • ②定义dao接口及其实现子类
    • ③编写spring.xml
    • ④代码测试
  • ①引入依赖

    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>5.3.16</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-beans</artifactId>
            <version>5.3.16</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.3.16</version>
        </dependency>
    
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-expression</artifactId>
            <version>5.3.16</version>
        </dependency>
    
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jcl</artifactId>
            <version>5.3.16</version>
        </dependency>
    
        <dependency>
            <groupId>commons-dbutils</groupId>
            <artifactId>commons-dbutils</artifactId>
            <version>1.7</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.2.8</version>
        </dependency>
    
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.49</version>
        </dependency>
    
    </dependencies>
    
  • ②定义dao接口及其实现子类

    public class UserDaoImpl implements UserDao {
    
    
        private QueryRunner queryRunner;
    
        public void setQueryRunner(QueryRunner queryRunner) {
            this.queryRunner = queryRunner;
        }
    
        public List<User> selectUserList() throws Exception {
            return  queryRunner.query(
                    "select * from t_user",
                    new BeanListHandler<User>(User.class)
            );
        }
    
    }
    
  • ③编写spring.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:context="http://www.springframework.org/schema/context"
           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
            http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
    
    
        <bean id="userDao" class="com.panghu.dao.impl.UserDaoImpl">
            <property name="queryRunner" ref="queryRunner"></property>
        </bean>
    
    
        <bean id="queryRunner" class="org.apache.commons.dbutils.QueryRunner">
            <constructor-arg name="ds" ref="dataSource"></constructor-arg>
        </bean>
    
        <!--加载jdbc.properties-->
        <context:property-placeholder location="jdbc.properties"></context:property-placeholder>
    
        <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
            <property name="driverClassName" value="${driverClassName}"></property>
            <property name="url" value="${jdbcUrl}"></property>
            <property name="username" value="${user}"></property>
            <property name="password" value="${password}"></property>
        </bean>
    
    </beans>
    
  • ④代码测试

    public class UserDaoTest {
    
        private ApplicationContext applicationContext;
    
        @Before
        public void init(){
            applicationContext = new ClassPathXmlApplicationContext("spring.xml");
        }
    
        @Test
        public void selectUserList() throws Exception {
            UserDao userDao = applicationContext.getBean(UserDao.class);
            List<User> userList = userDao.selectUserList();
            System.out.println("userList = " + userList);
        }
    }
    

02-IOC注解说明(了解)

  • 概述
    • 学习基于注解的 IoC 配置,大家脑海里首先得有一个认知,即注解配置和 xml 配置要实现的功能都 是一样的,都是要降低程序间的耦合。只是配置的形式不一样。
    • 关于实际的开发中到底使用xml还是注解,每家公司有着不同的使用习惯。所以这两种配置方式我们 都需要掌 握。

03-注解创建对象(掌握)

  • 概述

    • @Component , 通用注解,可以作用于任何实体类
    • @Controller , 作用于控制层的实体类,本质是@Component
    • @Service , 作用于业务层的实体类,本质是@Component
    • @Repository , 作用于持久层的实体类,本质是@Component
  • 代码实现

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:context="http://www.springframework.org/schema/context"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:cotnext="http://www.springframework.org/schema/context"
           xsi:schemaLocation="
           http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
           http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    
        <!--扫描注解-->
        <cotnext:component-scan base-package="com.panghu"></cotnext:component-scan>
    
    </beans>
    
    @Controller
    public class UserController {
    }
    
    @Service
    public class UserServiceImpl implements UserServcie {
    }
    
    @Repository
    public class UserDaoImpl implements UserDao {
    }
    
    @Component("user1")
    public class User {
    
        private Integer userId;
        private String userName;
        private String userPwd;
        private Double money;
        private String address;
    
    }
    
    
  • 代码测试

    public class AnnotationTest {
    
        private ApplicationContext applicationContext;
    
        @Before
        public void init(){
            applicationContext = new ClassPathXmlApplicationContext("spring.xml");
        }
    
        /*03-注解创建对象*/
        @Test
        public void test1(){
           applicationContext.getBean("user1");
           applicationContext.getBean("userController");
           applicationContext.getBean("userServiceImpl");
           applicationContext.getBean("userDaoImpl");
        }
    }
    
    

04-注解扫描详解(掌握)

  • 分类

    • ①基本扫描
    • ②指定要排除的组件
    • ③指定要扫描的组件
  • ①基本扫描

    <cotnext:component-scan base-package="com.panghu"></cotnext:component-scan>
    
    
  • ②指定要排除的组件

    <context:component-scan base-package="com.panghu">
        <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
    </context:component-scan>
    
    
  • ③指定要扫描的组件

    <context:component-scan base-package="com.panghu" use-default-filters="false">
        <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
    </context:component-scan>
    
    

05-注解依赖注入之@Autowired(掌握)

  • 概述

    • 使用注解执行依赖注入
  • 工作流程

    • image-20220328103208362
  • 代码实现

    @Controller
    public class UserController {
    
    
        @Autowired
        private UserServcie userService;
    
    
    
        public void selectUserList() throws Exception {
            System.out.println("UserController selectUserList");
            userService.selectUserList();
        }
    
    }
    
    
  • 注意事项

    • 使用@Autowired执行注入时,不需要提供set方法

06-注解依赖注入之@Qualifier(掌握)

  • 概述

    • 配置@Autowired注解使用,根据对象名称来执行自动装配
  • 代码实现

    @Controller
    public class UserController {
    
    
        @Autowired
        @Qualifier("userService2")
        private UserServcie userServcie;
    
    
        public void selectUserList() throws Exception {
            System.out.println("UserController selectUserList");
            userServcie.selectUserList();
        }
    
    }
    
    

07-@Autowired的其他细节(掌握)

  • ①标注在构造器

    @Component
    public class UserServiceWrapper {
    
        private UserServcie userServcie;
    
        @Autowired
        public UserServiceWrapper(UserServcie userServiceImpl) {
            this.userServcie = userServiceImpl;
        }
    }
    
    
  • ②标注在set方法

    @Component
    public class UserServiceWrapper2 {
    
        private UserServcie userServcie;
    
    
        @Autowired
        @Qualifier("userServiceImpl")
        public void setUserServcie(UserServcie userServcie) {
            this.userServcie = userServcie;
            System.out.println("userServcie = " + userServcie);
        }
    }
    
    
  • ③佛系装配 : 有就执行装配,没有就不装配

    @Controller
    public class UserController {
    
    
        @Autowired(required = false)
        @Qualifier("userServiceImpl3")
        private UserServcie userServcie;
    
    
        public void selectUserList() throws Exception {
            System.out.println("UserController selectUserList");
            userServcie.selectUserList();
        }
    
    }
    
    

08-注解依赖注入之@Resource(掌握)

  • 概述
    • JSR-250提供的,它是Java标准,绝大部分框架都支持。
  • 总结
    • 既指定name,也指定type
      • 都要考虑
    • 只指定name
      • 只考虑name
    • 只指定type
      • 只考虑type
    • 都没有指定
      • 先考虑对象名称,再考虑对象类型

09-注解依赖注入之@Value(掌握)

  • 概述

    • 给简单类型的变量执行自动装配,相当于
  • 代码实现

    @Component
    public class Student {
    
        @Value("1")
        private Integer stuId ;
    
        @Value("廖虚蕊")
        private String stuName;
    
    }
    
    

10-注解整合junit(掌握)

  • 开发步骤

    • ①引入依赖
      • spring-test
    • ②编写单元测试类
  • ①引入依赖

    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-test</artifactId>
        <version>5.3.16</version>
    </dependency>
    
    
  • ②编写单元测试类

    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration(locations = "classpath:spring.xml")
    public class AnnotationTest2 {
    
    
        @Autowired
        private UserController userController;
    
        @Test
        public void selectUserList() throws Exception {
            userController.selectUserList();
        }
    
    
    }
    
    

11-IOC新注解说明(掌握)

  • @Configuration
    • 用于指定当前类是一个 spring 配置类;相当于spring.xml
  • @ComponentScan
    • 用于指定 spring 在初始化容器时要扫描的包;相当于"<cotnext:component-scan base-package=“com.atguigu”>"
  • @Bean
    • 该注解只能写在方法上,表明使用方法创建一个对象,并且放入 spring 容器;
    • 相当于""
  • @PropertySource
    • 用于加载properties文件;相当于"<context:property-placeholder location=“jdbc.properties”>"
  • @Import
    • 用于导入其他的配置类;相当于""

12-IOC纯注解开发(掌握)

  • 需求

    • 将"01-Spring操作数据库"修改为纯注解配置.
  • 代码实现

    @Import(DataSourceConfiguration.class)
    @Configuration
    @ComponentScan("com.panghu")
    public class SpringConfiguration {
    
    
    }
    
    
    @Configuration
    @PropertySource("jdbc.properties")
    public class DataSourceConfiguration {
    
        @Value("${driverClassName}")
        private String driverClassName;
        @Value("${jdbcUrl}")
        private String url;
        @Value("${user}")
        private String username;
        @Value("${password}")
        private String password;
    
        @Bean
        public QueryRunner getQueryRunner(DataSource ds){
    
            return new QueryRunner(ds);
        }
    
        @Bean
        public DataSource getDataSource(){
            DruidDataSource dataSource = new DruidDataSource();
            dataSource.setDriverClassName(driverClassName);
            dataSource.setUrl(url);
            dataSource.setUsername(username);
            dataSource.setPassword(password);
            return dataSource;
        }
    }
    
    
    @Repository
    public class UserDaoImpl implements UserDao {
    
    
        @Autowired
        private QueryRunner queryRunner;
    
    
        public List<User> selectUserList() throws Exception {
            return  queryRunner.query(
                    "select * from t_user",
                    new BeanListHandler<User>(User.class)
            );
        }
    
    }
    
    
    public class UserDaoTest {
    
        private ApplicationContext applicationContext;
        @Before
        public void init(){
            applicationContext = new AnnotationConfigApplicationContext(SpringConfiguration.class);
        }
    
        @Test
        public void selectUserList() throws Exception {
            UserDao userDao = applicationContext.getBean(UserDao.class);
            List<User> userList = userDao.selectUserList();
            System.out.println("userList = " + userList);
        }
    }
    
    

13-IOC注解开发的作用和弊端(掌握)

  • 作用
    • image-20220328142949693
  • 总结
    • 开发过程中,既有注解,也有xml配置的.

14-AOP 概述(掌握)

  • 概述
    • 全称是 Aspect Oriented Programming 即: 面向切面编程。
  • 核心思想
    • AOP关注的是程序中的共性功能,开发时,将共性功能抽取出来制作成独立的功能模块,此时原始功 能中将不具有这些被抽取出的共性功能代码。在被抽取的共性功能的模块运行时候,将共性功能模块 也运行,即可完成原始的功能。
  • 作用
    • 在程序运行期间,不修改源码对已有方法进行增强。
  • 优势
    • 减少重复代码 提高开发效率 维护方便
  • 实现方式
    • 装饰模式
    • 动态代理技术
  • OOP vs AOP
    • OOP : 面向对象
    • AOP : 面向共性功能

15-AOP原理环境搭建(掌握)

  • 代码实现

    public class UserServiceImpl implements UserService {
    
    
        public void addUser() throws Exception {
            System.out.println("权限校验");
            System.out.println("UserServiceImpl addUser");
            System.out.println("日志记录");
        }
    
        public void deleteUser() throws Exception {
            System.out.println("权限校验");
            System.out.println("UserServiceImpl deleteUser");
            System.out.println("日志记录");
        }
    
        public void updateUser() throws Exception {
            System.out.println("UserServiceImpl updateUser");
        }
    
        public void selectUser() throws Exception {
            System.out.println("UserServiceImpl selectUser");
    
        }
    
    }
    
  • 存在问题

    • 主要功能:增加用户,删除用户,修改用户,查询用户辅助功能:权限校验,日志记录都写到一块了,不满足单一职责原则,耦合度较高.

16-动态代理之JDKProxy(掌握)

  • 工作原理

    • image-20220328153209159
  • 代码实现

    public class UserServiceJDKProxy {
    
        /**
         * 获取代理类对象
         *
         * @param userService : 被代理类对象
         * @return : 代理类对象
         */
        public static UserService getUserServiceJDKProxy(final UserService userService) {
    
            //ClassLoader loader : 被代理类的类加载器
            //Class<?>[] interfaces : 被代理类所实现的所有接口
            //InvocationHandler h : 方法增强的处理器
            UserService userServiceProxy = (UserService) Proxy.newProxyInstance(
                    userService.getClass().getClassLoader(),
                    userService.getClass().getInterfaces(),
                    new InvocationHandler() {
                        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                            //Object proxy : 代理类对象
                            //Method method : 被代理类的方法
                            //Object[] args : 方法的实际参数
                            Object result = null;
                            if (method.getName().equals("addUser") || method.getName().equals("deleteUser")) {
                                System.out.println("权限校验");
                                //被代理类对象 调用 被代理类方法
                                result = method.invoke(userService, args);
                                System.out.println("日志记录");
                            } else {
                                //selectUser,updateUser , 调用被代理类方法
                                result = method.invoke(userService, args);
    
                            }
    
                            return result;
                        }
                    }
            );
    
            return userServiceProxy;
    
        }
    
    
    }
    
    public class UserServiceJDKProxyTest {
    
        @Test
        public void addUser() throws Exception {
            //被代理类对象
            UserService userService = new UserServiceImpl();
            //代理类对象
            UserService userServiceJDKProxy = UserServiceJDKProxy.getUserServiceJDKProxy(userService);
    
            userServiceJDKProxy.addUser();
    
        }
    
        @Test
        public void deleteUser() throws Exception {
            //被代理类对象
            UserService userService = new UserServiceImpl();
            //代理类对象
            UserService userServiceJDKProxy = UserServiceJDKProxy.getUserServiceJDKProxy(userService);
            userServiceJDKProxy.deleteUser();
        }
    
        @Test
        public void updateUser() throws Exception {
            //被代理类对象
            UserService userService = new UserServiceImpl();
            //代理类对象
            UserService userServiceJDKProxy = UserServiceJDKProxy.getUserServiceJDKProxy(userService);
            userServiceJDKProxy.updateUser();
        }
    
        @Test
        public void selectUser() throws Exception {
            //被代理类对象
            UserService userService = new UserServiceImpl();
            //代理类对象
            UserService userServiceJDKProxy = UserServiceJDKProxy.getUserServiceJDKProxy(userService);
            userServiceJDKProxy.selectUser();
        }
    }
    
    

17-动态代理之CGLIB(掌握)

  • 工作流程

    • image-20220328162224393
  • 代码实现

    public class UserServiceCglibProxy {
    
    
        /**
         * 获取代理类对象
         *
         * @param clazz : 被代理类字节码对象
         * @return
         */
        public static UserService getUserServiceCglibProxy(final Class clazz) {
            Enhancer enhancer = new Enhancer();
            //代理类对象 继承 被代理类对象
            enhancer.setSuperclass(clazz);
            //执行方法增强
            enhancer.setCallback(new MethodInterceptor() {
                public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
                    //Object o : 代理类对象
                    //Method method : 被代理类方法
                    //Object[] args : 方法实际参数
                    //MethodProxy methodProxy : 代理类方法
                    Object result = null;
                    if ("addUser".equals(method.getName()) || "deleteUser".equals(method.getName())) {
                        System.out.println("权限校验");
                        //执行 被代理类的方法
                        //method.invoke(o,args);//错误
                        //method.invoke(clazz,args);//错误
                        //methodProxy.invoke(o,args);//错误
                        //由代理类对象 执行代理类方法 , 调用代理类方法的父方法(被代理的方法)
                        result = methodProxy.invokeSuper(o, args);
                        System.out.println("日志记录");
                    } else {
                        result = methodProxy.invokeSuper(o, args);
    
                    }
    
                    return result;
                }
            });
            Object userServiceCglibProxy = enhancer.create();
            return (UserService) userServiceCglibProxy;
    
        }
    
    }
    
    
    public class UserServiceCglibProxyTest {
    
        @Test
        public void addUser() throws Exception {
            UserService userServiceCglibProxy = UserServiceCglibProxy.getUserServiceCglibProxy(UserServiceImpl.class);
    
            userServiceCglibProxy.addUser();
    
        }
    
        @Test
        public void deleteUser() throws Exception {
            UserService userServiceCglibProxy = UserServiceCglibProxy.getUserServiceCglibProxy(UserServiceImpl.class);
    
            userServiceCglibProxy.deleteUser();
        }
    
        @Test
        public void updateUser() throws Exception {
            UserService userServiceCglibProxy = UserServiceCglibProxy.getUserServiceCglibProxy(UserServiceImpl.class);
    
            userServiceCglibProxy.updateUser();
        }
    
        @Test
        public void selectUser() throws Exception {
            UserService userServiceCglibProxy = UserServiceCglibProxy.getUserServiceCglibProxy(UserServiceImpl.class);
    
            userServiceCglibProxy.selectUser();
        }
    }
    
    
  • 总结

    • 被代理类对象有实现接口,使用JDKProxy动态代理,代理类和被代理类实现同一个接口.
    • 被代理类对象没有实现接口,使用CGLIB动态代理,代理类继承被代理类.

18-AOP名词解释(掌握)

  • 连接点:join point
    • 被代理类中的所有方法
  • 切入点: pointcut
    • 被代理类中的具有共性功能的方法
  • 目标对象类
    • 包含切入点方法的类
  • 通知: advice
    • 将共性功能抽取成独立的方法
  • 通知类
    • 包含通知方法的类
  • 切面:aspect
    • 通知和切入点的关系
  • 织入 : weave
    • 将共性功能(通知)动态放入到原方法(切入点)执行的过程

19-AOP入门案例(掌握)

  • 开发步骤

    • ①引入依赖
    • ②制作目标对象类
      • 切入点
    • ③制作通知类
      • 通知
    • ④编写spring.xml
      • 配置切面关系
    • ⑤代码测试
  • ①引入依赖

    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-aop</artifactId>
        <version>5.3.16</version>
    </dependency>
    
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-aspects</artifactId>
        <version>5.3.16</version>
    </dependency>
    
    
  • ②制作目标对象类

    @Service
    public class UserServiceImpl implements UserService {
    
    
        /**
         * 切入点
         * @throws Exception
         */
        public void addUser() throws Exception {
            System.out.println("UserServiceImpl addUser");
        }
    
        /**
         * 切入点
         * @throws Exception
         */
        public void deleteUser() throws Exception {
            System.out.println("UserServiceImpl deleteUser");
        }
    
        public void updateUser() throws Exception {
            System.out.println("UserServiceImpl updateUser");
        }
    
        public void selectUser() throws Exception {
            System.out.println("UserServiceImpl selectUser");
    
        }
    
    }
    
    
  • ③制作通知类

    @Component
    public class MyAdvice1 {
    
    
        /**
         * 通知
         */
        public void checkPermission(){
            System.out.println("权限校验");
        }
    
        /**
         * 通知
         */
        public void printLog(){
            System.out.println("日志记录");
        }
    
    }
    
    
  • ④编写spring.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"
           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/context https://www.springframework.org/schema/context/spring-context.xsd
           http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd">
    
        <context:component-scan base-package="com.atguigu"></context:component-scan>
    
        <!--配置切面-->
        <aop:config>
    
            <!--通知和切入点的关系-->
            <aop:aspect ref="myAdvice1">
                <aop:before method="checkPermission"
                            pointcut="execution(public void com.atguigu.service.impl.UserServiceImpl.addUser())"></aop:before>
                <aop:after method="printLog"
                           pointcut="execution(public void com.atguigu.service.impl.UserServiceImpl.addUser())"></aop:after>
            </aop:aspect>
    
        </aop:config>
    
    </beans>
    
    
  • ⑤代码测试

    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration(locations = "classpath:spring.xml")
    public class AOPTest {
    
        @Autowired
        private UserService userService;
    
        @Test
        public void addUser() throws Exception {
            userService.addUser();
        }
    
        @Test
        public void selectUser() throws Exception {
            userService.selectUser();
        }
    
    }
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值