Spring框架2

基于注解的ioc

也称为DI()他是ioc的具体实现的技术

基于注解的IOC,必须要在Spring的核心配置文件中添加包扫描

    <!--添加包扫描-->
    <context:component-scan base-package="com.pjpower.s01"></context:component-scan>
</
  • 药:创建对象并注入

  • 汤:xml 注解annotation

    1. 创建对象注解

      • @Component:可以创建任何对象,创建的对象的默认名称是类名的驼峰命名法,也可以指定对象的名称@Component(“指定名称”)

      • @Controller:专门用来创建控制器对象(Servlet),这种对象可以接收用户的请求,可以返回结果给客户端

      • @Service专门用来创建业务逻辑层对象,负责向下访问数据访问层,处理完毕后的结果会返回给界面层

      • @Repository:专门用来创建数据访问层对象,负责数据库中的增删改查操作

    2. 依赖注入的注解

      1. 简单类型(八种基本类型和String类型)的注入

        @Value:用来给简单类型注入值

      2. 引用类型的注入

        • @Autowired:使用简单类型注入值,从整个bean工厂中搜索同源类型的象进行注入

          什么是同源类型?

          1. 被注入的类型(Student中的School)与注入类型是完全相同的类型
          2. 被注入的类型(Student中的School父)与注入类型(子)是父子类
          3. 被注入的类型(Student中的Schoo接口)与注入类型(实现类)是接口和实现类的类型

          注意:在有父类的情况下,使用按类型注入,就意味着有多个可注入的对象,此时按照名称进行筛选,选中与被注入对象相同名称的对象进行注入

        • @Autowired

          @Qualifior:使用名称注入值,,从整个bean工厂中搜索同源类型的象进行注入

      添加包扫描的方式:

      1. 单个包扫描(推荐使用)

            <context:component-scan base-package="com.bjpowernode.service.impl"></context:component-scan>
        
        
      2. 支持多个包扫描,多个包之间用逗号或者空格或者分号分隔

        <context:component-scan base-package="com.bjpowernode.service.impl com.bjpowernode.dao.impl com.bjpowernode.controller"></context:component-scan>
        
      3. 扫描根包(不推荐,会降低容器启动速度)

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

    为应用指定多个Spring配置文件

    当项目越来越大时,需要多人共同开发,一个配置就存在很大的隐患,我们需要拆分配置文件

    • 拆分配置文件的策略

      1. 按层拆

        界面层

        applicationContext_controller.xml

        <bean id="uController" class="com.bjpower.controller.UserController"></bean>
        <bean id="bController" class="com.bjpower.controller.BookController"></bean>
        

        业务逻辑层

        applicationContext_service.xml

        <bean id="uService" class="com.bjpower.cervice.UserService"></bean>
        <bean id="bService" class="com.bjpower.service.BookService"></bean>
        

        数据访问层

        applicationContext_mapper.xml

        <bean id="uMapper" class="com.bjpower.mapper.UserMapper"></bean>
        <bean id="bMapper" class="com.bjpower.mapper.BookaMapper"></bean>
        
      2. 按功能拆

        按用户分类

        applicationContext_users.xml

        <bean id="uController" class="com.bjpower.controller.UserController"></bean>
        <bean id="uService" class="com.bjpower.cervice.UserService"></bean>
        <bean id="uMapper" class="com.bjpower.mapper.UserMapper"></bean>
        

        按书本分类

        applicationContext_books.xml

        <bean id="bController" class="com.bjpower.controller.BookController"></bean>
        <bean id="bService" class="com.bjpower.service.BookService"></bean>
        <bean id="bMapper" class="com.bjpower.mapper.BookaMapper"></bean>
        

    Spring配置文件的整合

    1. 单个文件导入多个文件的导入
    2. 批量导入

    面向切面编程AOP

    ​ AOP(Aspect Orient Programming) ,面向切面编程

    ​ 切面:公共的,通用的,重复的功能称之为切面,面向切面编程就是将切面取出来,单独开发,在需要调用的方法中通过动态代理的方式进行织入。

手写AOP框架

业务:图书购买业务

切面:事务

  1. 起一个版本:业务和切面紧耦合,没有拆分
/**
 * 图书购买页面和事务紧贴在一起
 */
public class BookServiceImpl {

    public void buy() {

        try {
            System.out.println("事务开启");
            System.out.println("图书购买功能的实现");
            System.out.println("提交事务");
        } catch (Exception e) {
            System.out.println("事物的回滚");
        }
    }
}

  1. 第二个版本:使用子类代理的方式拆分业务和切面
/**
 * 使用子类代理来实现业务和切面的拆分*/
public class BookServiceImpl {
    public  void buy(){
        System.out.println("购买业务的实现");
    }
}
/**
 * 字类代理实现,将父类的业务添加到事物之中
 */
public class SubBookServiceImpl extends BookServiceImpl {
    @Override
    public void buy() {
        try {       //事物的开启
            System.out.println("开启。。。。。。。。");
            //业务的实现
            super.buy();

            //事物的提交
            System.out.println("提交。。。。。。。。");
        } catch (Exception e) {
            System.out.println("事物的回滚。。。");
        }

    }
}
  1. 第三个版本:使用静态代理拆分业务和切面,此时业务和业务接口已经拆分,此使切面紧耦合在业务中
public interface Service {
    //规定业务功能
    void buy();
}

/**
 *   目标,业务功能的具体实现
 */
public class BookServiceImpl implements Service{

    @Override
    public void buy() {
        //
        System.out.println("图书购买功能的具体实现");
    }
}

/**
 *   目标,业务功能的具体实现
 */
public class BookServiceImpl implements Service{

    @Override
    public void buy() {
        //
        System.out.println("图书购买功能的具体实现");
    }
}

测试类:

public class Test03 {
    @Test
    public  void test03(){
        Service agent =new Agent(new BookServiceImpl());
        agent.buy();
    }
    @Test
    public  void test031(){
        Service agent =new Agent(new ProductServiceImpl());
        agent.buy();
    }
}
  1. 第四个版本,使用静态代理拆分业务和业务接口,切面和切面接口
public interface Service {
    void buy();
}
public class BookServiceImpl  implements Service{
    @Override
    public void buy() {
        System.out.println("图书购买功能的实现。。。。。。");
    }
}
public interface Aop {
    //事务开启
    default void before(){};
    //提交事务
    default void after(){};
    //事务回滚
    default void exception(){};
}

public class TransAop implements Aop {
    @Override
    public void before() {
        System.out.println("事务开启。。。。。。。");
    }

    @Override
    public void after() {
        System.out.println("事务提交。。。。。。。");
    }

    @Override
    public void exception() {
        System.out.println("事务回滚。。。。。。。");
    }
}

public class Agent implements Service {
    public Service target;//业务对象
    public Aop aop;//切面对象

    public Agent(Service target, Aop aop) {
        this.target = target;
        this.aop = aop;
    }

    @Override
    public void buy() {
        try {
            aop.before();//事物的开启
            target.buy();
            aop.after();//事务的提交
        } catch (Exception e) {
            aop.exception();//事务回滚
        }
    }
}

测试类:

public class Test04 {
    @Test
    public  void test4(){
        Service agent = new Agent( new BookServiceImpl(),new TransAop());
        agent.buy();
    }

    @Test
    public  void test5(){
        Service agent = new Agent( new BookServiceImpl(),new TransAop());
        //将日志添加进去
        Service agent1 =new Agent(agent,new LogAop());
        agent1.buy();
    }
}
  1. 第五个版,使用动态代理完成第四个版本的优化
public interface Service {
    //规定业务功能
    void buy();

    //增加有参数有返回值的方法测试代理功能
    default  String show(int age){return  null;}

}
public class BookServiceImpl implements Service {
    @Override
    public void buy() {
        System.out.println("图书购买功能的实现。。。。。。");
    }

    @Override
    public String show(int age) {
        System.out.println("这是show 方法被调用。。。。。");
        return "年龄是"+age+"岁";
    }
}

public interface Aop {
    //事务开启
    default void before(){};
    //提交事务
    default void after(){};
    //事务回滚
    default void exception(){};
}

public class LogAop implements Aop {
    @Override
    public void before() {
        System.out.println("前置日志输出。。。。。");
    }
}

public class TransAop implements Aop {
    @Override
    public void before() {
        System.out.println("事务开启。。。。。。。");
    }

    @Override
    public void after() {
        System.out.println("事务提交。。。。。。。");
    }

    @Override
    public void exception() {
        System.out.println("事务回滚。。。。。。。");
    }
}

public class ProxyFactory {
    public static Object getAgent(Service target, Aop aop) {
        //返回生成的动态代理对象
        return Proxy.newProxyInstance(
                //类加载器
                target.getClass().getClassLoader(),
                //目标对象实现的所有接口
                target.getClass().getInterfaces(),
                //代理功能的实现
                new InvocationHandler() {
                    @Override
                    public Object invoke(
                            //生成的代理对象
                            Object proxy,
                            //正在被调用的目标方法buy(),show()
                            Method method,
                            //设置目标方法的参数
                            Object[] args) throws Throwable {
                        Object obj = null;
                        try {
                            //切面
                            aop.before();
                            //业务
                            obj = method.invoke(target, args);
                            //切面
                            aop.after();
                        } catch (Exception e) {
                            //切面
                            aop.exception();//回滚事务
                        }
                        return obj;
                    }
                }
        );
    }
}

测试类代码:

public class Test05 {
    @Test
    public void test05() {

        //得到动态代理对象
        Service agent = (Service) ProxyFactory.getAgent(new BookServiceImpl(), new TransAop());
        agent.buy();
    }

    @Test
    public void test06() {

        //得到动态代理对象
        Service agent = (Service) ProxyFactory.getAgent(new BookServiceImpl(), new TransAop());
        //加入日志
        Service agent1 = (Service) ProxyFactory.getAgent(agent, new LogAop());
        String show = agent1.show(22);
        System.out.println(show);
    }
}

Spring 支持AOP的编程,常有以下几种:

  1. before通知:在目标方法被调用之前,涉及接口org.springframework.aop.MethodBeforeAdvice;
  2. After通知:在目标方法被调用之后调用,涉及接口org.springframework.aop.AfterReturningAdvice;
  3. Throws通知:目标方法抛出异常时调用,涉及接口org.springframework.aop.ThrowsAdvice;
  4. Around通知:拦截对目标对象方法调用,涉及接口org.springframework.aop.MethodInterceptor;

AOP常用术语:

  1. 切面:就是那些重复的公共的,通用的功能称之为切面,例如日志,事务,权限。
  2. 连接点L:就是目标方法,因为在目标方法中要实现目标方法的功能和切面功能
  3. 切入点(Pointcut):指定切入的位置,多个连接点构成切入点,切入点可以是一个目标方法,可以是一个类中的所有方法,也可以是某个报下所有类中的方法
  4. 目标对象:操作谁,谁就是目标对象
  5. 通知(Advice):来指定切入的时机,就是在目标方法执行前,执行后或是出错时,还是环绕目标方法切入切面功能
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值