Spring5【学习笔记二】

IOC操作Bean管理

1.普通bean:在配置文件中定义bean类型就是返回类型

2.工厂bean:在配置文件定义bean类型可以和返回类型不一致

步骤:

--创建类,让这个类作为工厂bean,实现接口FactoryBean

--实现接口里的方法,在实现的方法定义返回的bean 类型

<?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:p="http://www.springframework.org/schema/p"
       xmlns:c="http://www.springframework.org/schema/c"
       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">
<!--使用Spring创建对象,,即bean-->
    <bean id="hello" class="com.wang.pojo.Hello">
        <property name="name" value="spring"></property>
    </bean>
</beans>
package com.wang.pojo;

import org.springframework.beans.factory.FactoryBean;

public class Hello implements FactoryBean<User> {
    private String name;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public void show(){
        System.out.println("hello"+this.name);
    }
    @Override
    public User getObject() throws Exception {
        User user = new User("wang",20);
        return user;
    }
    @Override
    public Class<?> getObjectType() {
        return null;
    }

    @Override
    public boolean isSingleton() {
        return FactoryBean.super.isSingleton();
    }
}
@Test
    public void HelloTest(){
        //获取Spring的上下文对象
        ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");
        //对象都在Spring中管理,使用时 直接取出即可
        User hello = (User) context.getBean("hello");
        System.out.println(hello);
    }

 

Spring针对Bean管理中创建对象提供注解

  1. @Component
  2. @Service
  3. @Controller
  4. @Repository

*上面四个注解功能一样,都用来创建bean实例

基于注解创建Bean实例

 <!--开启全包扫描:
    扫描多个包,逗号隔开。
    或者直接使用共同父包
 -->
    <context:component-scan base-package="com.wang"></context:component-scan>
    <!--实例一:不使用默认的过滤器,中间代表自定义过滤器:只扫描Controller注解 -->
        <context:component-scan base-package="com.wang" use-default-filters="false">
            <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
        </context:component-scan>
    <!--    实例二:(排除)不扫描Controller -->
        <context:component-scan base-package="com.wang" use-default-filters="false">
            <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
        </context:component-scan>
//注解中value可以省略,省略的话,默认值是类名(首字母小写)
@Component
public class UserService {
    @Resource
    UserDao userDao;
    public void say(){
        System.out.println("userService say....");
        userDao.say();
    }
}

将注解component换成以上任意一个都可以实现对象的创建

@Test
    public void userService(){
        ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");
        context.getBean("userService", UserService.class).say();
    }

基于注解方式实现属性的注入

@AutoWired:根据属性类型进行自动装配,所以不需set方法!!

@Qualifier:根据属性名称进行注入,要和AutoWired一起使用!

@Resource:根据类型注入,也可以根据名称注入(需要注意的是,Resource是javax扩展包中的,其他注解是Spring自带的)

@Value:根据普通类型注入

public interface UserDao {
    public void say();
}

package com.wang.dao;

import org.springframework.stereotype.Repository;

@Repository
public class UserDaoImp implements UserDao{
    @Override
    public void say() {
        System.out.println("dao say....");
    }
}
@Service
public class UserService {
    @Resource
    UserDao userDao;
    public void say(){
        System.out.println("userService say....");
        userDao.say();
    }
}

 

完全注解开发

创建配置类,替代xml

原xml形式,里面只配置了扫描注解的路径,所以配置类中也只需要配置路径

package com.wang.config;

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

@Configuration
@ComponentScan(basePackages = {"com.wang"})//开启包内扫描
public class MyConfig {
}
@Test
    public void userService(){
        ApplicationContext context = new AnnotationConfigApplicationContext(MyConfig.class);
        context.getBean("userService", UserService.class).say();
    }

由读取xml文件改成读取配置类,其他保持不变

Bean的作用域

在Spring可以设置bean实例是单实例还是多实例:

Bean scope属性

默认单例模式,共享一个对象,scope=“singleton”

原型模式,scope=“prototype”

单例模式时,加载Spring配置文件时就会创建单实例对象

原型模式时,是每次在获取bean(getBean())新创建一个对象

Bean的生命周期

从对象的创建到对象销毁的过程

  1. 通过构造器(无参)去创建Bean实例
  2. 为Bean属性设置值和对其他Bean的引用(set的方法)
  3. 调用Bean里的初始化的方法(需要配置)
  4. Bean使用(获取到对象)
  5. 当容器关闭时,调用Bean的销毁方法(需要自己配置)

Spring中AOP(面向切编程)

对业务逻辑的各个部分进行隔离,从而使得业务了逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率

不通过修改源代码方式,在主干功能里添加新功能

AOP底层使用动态代理的情况

  1. 有接口的情况,使用JDK动态代理
  2. 无接口的情况,使用CGLIB动态代理

JDK动态代理

场景分析:在不动底层代码的情况下,在用户登录之前去判断该用户的权限

public interface UserDao {
    public void login(String name,String pwd);
}
package com.wang.dao;

import org.springframework.stereotype.Repository;

@Repository
public class UserDaoImp implements UserDao{
  
    @Override
    public void login(String name, String pwd) {
        System.out.println("用户:"+name+"密码:"+pwd+"正在登录");
    }
}

MyInvocationHandler中写增强方法的逻辑,即先获取被增强方法的类对象(userDao),为了方法的通用,使用Object,通过构造器在创建MyInvocationHandler对象时,将userDao传进来,method.invoke即利用反射去调用传进来对象(userDao)的指定方法,参数一该对象,参数二该方法的参数

public class MyInvocationHandler implements InvocationHandler {
    Object obj;
    public MyInvocationHandler(Object obj){
        this.obj = obj;
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("判断该用户的权限");
        Object invoke = method.invoke(obj, args);
        System.out.println("登陆成功!");
        return null;
    }
}

newProxyInstance(参数1,参数2,参数3)

  1. 类加载器
  2. 增强方法所在的类,这个类实现的接口,支持多个接口
  3. 实现接口InvocationHandler,创建代理对象,写增强的逻辑方法
@Test
    public void userProxy(){
        Class<?>[] a = new Class[]{UserDao.class};
        UserDao o = (UserDao) Proxy.newProxyInstance(MyTest.class.getClassLoader(), a, new MyInvocationHandler(new UserDaoImp()));
        o.login("wang","123");
    }

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值