Spring_day02

一、IOC 注解开发

1. 注解和xml的配置对比

  • xml

    优点
    
        代码集中、容易查找、统一管理
    
    缺点
    
        代码量大
    
  • 注解

    优点
    
        代码量少、方便、简单
    
    缺点
    
        查找比较麻烦、因为注解比较零散
    

2. IOC注解入门

  1. 导入jar包

spring-aop-xxx.jar

  1. 导入约束 context约束

    <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 http://www.springframework.org/schema/context/spring-context.xsd">
    
  2. 在applicationContext.xml中打开注解的扫描开关

    <!-- 打上注解扫描的开关,其实就是让spring去扫描对应的类上是否有注解,如果有,就解析注解 -->
    <context:component-scan base-package="com.itheima.service.impl"></context:component-scan>
    
  3. 在需要托管的具体类上面上注解,并且指定标识符

    //  Component :直译过来就是组件。  代码会分三层,每一层的具体类、 都称之为组件
    @Component(value="us")  //@Component : 光打上这个注解,就是告诉spring,要托管这个类。  还得让spring解析这个注解,以便得到us标识符
    public class UserServiceImpl implements UserService {
    

3. 解释

xml : 

    注解扫描开关有两种写法:  但是建议使用第一种

        <!-- 打上注解扫描的开关,其实就是让spring去扫描对应的类上是否有注解,如果有,就解析注解 -->
        <context:component-scan base-package="com.itheima"></context:component-scan>

        <!-- 还有另一种写法: 不推荐使用  这个只能扫描在xml里面登记的类-->
       <!--     <context:annotation-config/> -->

注解:

    @Component("us") 

        @Component : 等同于是告诉spring托管这个类

        "us" : 等同于声明一个标识 类似bean里面的id 

    如果上面都不写就只是声明一个注解@Component 那么默认也会有一个标识符,这个标识符就是类名(但是第一个字母小写)  如: UserServiceImpl   :   id== userServiceImpl

4. 注解创建对象

  1. 注解创建多实例

    默认创建的实例还是单例的
    @Scope("prototype")
    
  2. 给类打上注解,以便让spring托管它,并且和标识符形成映射关系,都是靠@Component注解来实现
    但是由于web项目采用分层的结构, controller 、 service 、 dao 层, spring为了迎合这种趋势,它也把注解稍微再细分了一下:

    @Component
    
        @Repository("userDao") //持久层
        @Service("us") //业务逻辑层
        @Controller("action") //控制层
    
  3. 指定初始化&销毁方法

    @PostConstruct //用于定义指定方法为初始化方法
    public void init(){
        System.out.println("调用了UserServiceImpl的init方法~~");
    }
    
    @PreDestroy //用于定义指定方法为销毁时调用的方法
    public void destory(){
        System.out.println("调用了UserServiceImpl的destroy方法~~");
    }
    

5. DI的注解

注入普通数据:

    普通数据其实可以不用注解的方式来注入,直接写上赋值即可。

        @Value("北京")
        private String address;

注入对象数据


    早期的xml注入:

            <!--1.  这行代码就是让spring托管这个类,然后给这个类打上一个标识符 
                在这个类上面打上注解
            -->
            <bean id="ud" class="com.itheima.dao.impl.UserDaoImpl"></bean>

            <bean id="us" class="com.itheima.service.impl.UserServiceImpl">

                <!-- 2. 把ud对应的类实例给注入到userDao中 -->
                <property name="userDao" ref="ud"></property>
            </bean>

    注解的注入

        1. 在需要注入进来的那个类打上注解,让spring托管它

            @Repository("ud")
            public class UserDaoImpl implements UserDao{

        2. 在成员属性上使用注解来注入对象


             @Resource(name="ud") //根据给定的标识符找到具体的类   name="" ====> ref=""

            //@Autowired //自动找到这个接口的实现类然后注入进来
            private UserDao userDao ;

如果只有一种实现的情况,又懒得写太多,就可以直接使用 @Autowired 。 但是如果存在多种实现,又想指定具体的某一个实现,那么请使用 @Resource(name=”标识符”)

6. xml 和 注解 混合使用

使用xml来托管bean , 使用 注解来注入属性

二、 Spring测试

  1. 导入jar包

    spring-test-xxx.jar

  2. 在测试类上面打上注解,指定运行环境以及xml文件所在

  3. 给成员打上注解,注入对象即可

    //指定当前测试使用的运行环境, 除了兼备以前junit的运行环境之外 还会解析xml 创建工厂
    @RunWith(SpringJUnit4ClassRunner.class)  
    
    //指定以下xml文件在哪里
    @ContextConfiguration("classpath:applicationContext.xml")
    public class MainTest {
    
        //只有在测试类里面 用到的那些注解,不用打开注解扫描开关,但是在service\dao\action里面有注解的话,那么请打开注解扫描开关。
        @Autowired
        private UserService userService;
    
        @Test
        public void testSave(){
            userService.save();
        }
    
    }
    

三、AOP

  • 什么是AOP?

AOP(Aspect Oriented Programming,面向切面编程),可以说是OOP(Object Oriented Programing,面向对象编程)的补充和完善。

具体应用在: 不想改动源码的前提下还想对这份功能进行扩展和增强。

icon

1. AOP的底层原理

虽然已经知道了AOP就是用来做增强、扩展的。 可选的方案无非就是装饰者模式 、 代理模式(静态代理、 动态代理) 。 spring的aop采用了动态代理的手法。两种动态代理实现

icon

  • 基于JDK的动态代理

真实类实现具体的接口,做出来接口的又一个实现类作为代理类

    @Test
    public void testJdkProxy(){
        //1. 创建真实对象
        final UserService userService = new UserServiceImpl();

        //2. 创建代理
        UserService proxyObj = (UserService) Proxy.newProxyInstance(
                userService.getClass().getClassLoader(), //类加载器。 一般这里就采用真实类用什么类加载器,这里就写什么类加载器
                userService.getClass().getInterfaces(), //真实类实现什么接口,这里就写什么接口。也就是表示了代理类实现什么接口
                new InvocationHandler() { //用于处理代理对象调用方法的回调

                    /*
                     * 外面使用代理对象调用方法,这个invoke方法就会执行。(non-Javadoc)
                     * method : 外面具体的方法引用。
                     * args :外面调用的方法参数
                     */
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

                        //Logger.log();
                        if(method.getName().equals("save")){
                            System.out.println("执行了输出日志的功能");
                        }
                        //采用反射的手法调用真实对象中的方法
                        return  method.invoke(userService, args);
                    }
                });

        //3. 使用代理对象调用方法
         proxyObj .save();  // 外面调用的是代理对象的方法,背后真正干活是真实对象, 也就是userService.save();
    }
  • 基于Cglib动态代理

真实类没有实现任何接口, 做出来真实类的又一个子类作为代理类

    @Test
    public void testCglibProxy(){
        //1. 创建真实对象
        final ProductService  productService = new ProductService();

        //2. 创建代理对象enhancer 不是代理对象。 只是要借助它来创建代理对象
        Enhancer enhancer = new Enhancer();

        //设置父类是谁
        enhancer.setSuperclass(ProductService.class);
        //设置回调。用于处理用代理对象调用方法之后,里面要调用真实的方法
        enhancer.setCallback(new MethodInterceptor() {
            @Override
            public Object intercept(Object arg0, Method arg1, Object[] arg2, MethodProxy arg3) throws Throwable {

                System.out.println("输出日志~");
                return arg1.invoke(productService, arg2);
            }
        });

        //创建出来代理对象
        ProductService proxyObj = (ProductService) enhancer.create();
        proxyObj.save();
    }

2. AOP术语

icon

3. AOP入门

  1. 导包

四、总结

1. IOC注解 【重点】

    1. 导入jar包 

        spring-aop-xxx.jar

    2. 导入约束

        context约束

    3. 打开注解扫描开关

        <context:component-scan base-package="">

    4. 在类上面打上注解

        @Component

            @Repository
            @Service
            @Controller

    5. DI 注入 【重点】

        @Autowired

        @Resource(name="")

2. Spring测试

    1. 导入spring-test-xx.jar

    2. 添加注解

        @Runwith(SpringJunit4ClassRunner.class)
        @ContextConfiguration("classpath:applicationContext.xml")

        测试类里面的注解不用打开扫描开关

3. AOP

    1. aop是什么,有什么用

        面向切面编程,在不改动源码的前提下对功能进行扩展、增强

    2. aop的底层

        动态代理 : jdk  + cglib

    3. aop入门【重点】

        a. 导入jar包 :  4个  

            aop联盟包 、 aspectJ实现包  spring-aop-xxx.jar  spring -aspect-xx.jar

        b. 导入约束

            aop约束

        c. 托管业务逻辑类和 扩展的功能类

        d. 配置aop

            <aop:config>
                <aop:aspect ref="logger">
                    <!-- 前置增强 -->
                    <aop:before method="log" pointcut="execution(* com.itheima.service.impl.*.*(..))"/> 
                </aop:aspect>
         </aop:config>
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值