• Spring笔记整理


    IOC概念解析

    ioc简单代码示例
    IMessage.java

        public interface IMessage {
        	public abstract String getMessage();
            }
    

    Message.java

    public class Message implements IMessage {
        @Override
        public String getMessage() {
        return "Hello World!";
        }
    }
    

    NewMessage.java

    public class NewMessage implements IMessage {
        	@Override
        	public String getMessage() {
        		return "Hello Every One!";
        	}
        }
    

    message.properties

        1=com.alyshen.spring.Message
        2=com.alyshen.spring.NewMessage
    

    MessageFactory.java

        public class MessageFactory {
        
        	public static IMessage create(String key) {
        
        //		if ("1".equals(key)) {
        //			//工厂还是依赖这个类
        //			return new Message();
        //		}
        //		
        		// 使用资源文件
        		ResourceBundle bundle = ResourceBundle.getBundle("message");
        		String _class = bundle.getString(key);
        		try {
        			return (IMessage) Class.forName(_class).newInstance();
        		} catch (InstantiationException e) {
        			e.printStackTrace();
        		} catch (IllegalAccessException e) {
        			e.printStackTrace();
        		} catch (ClassNotFoundException e) {
        			e.printStackTrace();
        		}
        		return null;
        	}
        }
    

    MainClass.java

        public class MainClass {
        
        	public static void main(String[] args) {
        		// 这个类强依赖Message这个类
        		// Message msg = new Message();
        		
        		// 我们不想看到Message这个具体的产品
        		// IMessage msg = new Message();
        
        		IMessage msg = MessageFactory.create("1");
        		System.out.println(msg.getMessage());
        
        		msg = MessageFactory.create("2");
        		System.out.println(msg.getMessage());
        	}
        }
    

    Spring环境配置及IOC工厂应用

    用到的包以及文件

    包以文件 说明
    applicationContext.xml Spring配置文件
    spring-context-3.2.0.M1.jar 主要提供bean工厂的实现类,工厂就在里头,但是接口在spring-beans-3.2.0.M1.jar里头
    spring-beans-3.2.0.M1.jar bean工厂在里头
    spring-core-3.2.0.M1.jar Spring核心包
    spring-expression-3.2.0.M1.jar 支持spring表达式的
    spring-asm-3.2.0.M1.jar 动态生成一些类的(动态生成字节码的类)
    commons-logging-1.1.1.jar 依赖包(公共日志包)

    spring配置文件: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"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
    
        <bean id="msg1" class="com.alyshen.spring.Message" />
        <bean id="msg2" class="com.alyshen.spring.NewMessage" />
    </beans>
    

    使用spring的bean工厂

    public class MainClass {
        public static void main(String[] args) {
        // 使用spring 的bean工厂
        BeanFactory factory = new ClassPathXmlApplicationContext(
        "applicationContext.xml");
        // 使用通配符
        // BeanFactory factory = new ClassPathXmlApplicationContext("app*.xml");
    
        IMessage msg = (IMessage) factory.getBean("msg1");
        System.out.println(msg.getMessage());
    
        // 我们自己的bean工厂
        msg = MessageFactory.create("2");
        System.out.println(msg.getMessage());
        }
    }
    

    Spring依赖注入的基本方法

    set方法注入示例
    UserManager.java

    public class UserManager {
        // 依赖set方法注入
        private String driverCalss;
        private String url;
        private String username;
        private String password;
    
        public void addUser() {
            System.out.println(this.toString());
            System.out.println("用户管理_添加用户!");
        }
    
        public void setDriverCalss(String driverCalss) {
        	this.driverCalss = driverCalss;
        }
    
        public void setUsername(String username) {
        	this.username = username;
        }
    
        public void setPassword(String password) {
        	this.password = password;
        }
    
        public void setUrl(String url) {
        	this.url = url;
        }
    
        @Override
        public String toString() {
            return "UserManager [driverCalss=" + driverCalss + ", url=" + url
            + ", username=" + username + ", password=" + password + "]";
        }
    }
    

    UserAction.java

    public class UserAction {
        private UserManager manager = null;
    
        public void setManager(UserManager manager) {
        System.out.println("调用属性manager的set方法注入!");
        this.manager = manager;
        }
    
        public String execute() {
        this.manager.addUser();
        return "success";
        }
    }
    

    spring配置文件: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"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
    
        <bean id="userAction" class="com.alyshen.spring.UserAction">
            <!-- 
            通过属性的set方法将实例的注入 
            -->
            <property name="manager" ref="userManager" />
            </bean>
    
            <bean id="userManager" class="com.alyshen.spring.UserManager">
            <!-- 
            通过属性的set方法将数据的注入 
            -->
            <property name="driverCalss" value="jdbc.mysql.Driver" />
            <property name="username" value="root" />
            <property name="password" value="654321" />
            <property name="url" value="jdbc:mysql://localhost:3306/mydb" />
        </bean>
    </beans>
    

    MainClass.java

    	public static void main(String[] args) {
    	
    		// 使用spring 的bean工厂
    		BeanFactory factory = new ClassPathXmlApplicationContext(
    				"applicationContext.xml");
    		// BeanFactory factory = new ClassPathXmlApplicationContext("app*.xml");
    	
    		UserAction ua = (UserAction) factory.getBean("userAction");
    		System.out.println(ua.execute());
    	}
    

    Scope属性和BeanFactoryAware接口

    UserManager.java

    public class UserManager {
    
        // 依赖set方法注入
        private String driverCalss;
        private String url;
        private String username;
        private String password;
    
        public void addUser() {
            System.out.println("用户管理_添加用户!");
        }
        //各种set及get方法
        ……
    }
    

    UserAction.java

    /**
    * 实现接口BeanFactoryAware
    */
    public class UserAction implements BeanFactoryAware {
        private UserManager manager = null;
    
        public void setManager(UserManager manager) {
            // System.out.println("调用属性manager的set方法注入!");
    
            this.manager = manager;
        }
    
        public String execute() {
            // 每次调用这方法都重新创建bean工厂耗费资源,丧失性能
            // BeanFactory factory = 
            // 		new ClassPathXmlApplicationContext("applicationcontext.xml");
    
            // 非要实现单列对象注入多例对象属性实现:
            // 重新为属性赋值
            manager = (UserManager) factory.getBean("userManager");
    
            System.out.println(manager);
            this.manager.addUser();
            return "success";
        }
    
        BeanFactory factory = null;
    
        @Override
        public void setBeanFactory(BeanFactory factory) throws BeansException {
            // TODO Auto-generated method stub
            this.factory = factory;
        }
    }
    

    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"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
    
        <!-- 
        scope="singleton":单例(默认),因为是单例,所以属性在创建实例时注入一次,
        如果想多次注入属性实体,见 UserAction.java,首先注入的属性实体必须是多例
        不使用工厂注入
        scope="prototype":多例 
        -->
        <bean id="userAction" class="com.alyshen.spring.UserAction"
            scope="singleton">
            <!-- 
            通过属性的set方法将实例的注入 
            <property name="manager" ref="userManager" />
            -->
        </bean>
    
        <bean id="userManager" class="com.alyshen.spring.UserManager"
            scope="prototype">
            <!-- 通过属性的set方法将数据的注入 -->
            <property name="driverCalss" value="jdbc.mysql.Driver" />
            <property name="username" value="root" />
            <property name="password" value="654321" />
            <property name="url" value="jdbc:mysql://localhost:3306/mydb" />
        </bean>
    </beans>
    

    MainClass.java

    public static void main(String[] args) {
    	// UserAction userAction = new UserAction();
    	// UserManager manager = new UserManager();
    	// userAction.setManager(manager);
    
    	// 使用spring 的bean工厂
    	// BeanFactory factory = new ClassPathXmlApplicationContext("app*.xml");
    	BeanFactory factory = new ClassPathXmlApplicationContext(
    			"applicationcontext.xml");
    	UserAction ua = (UserAction) factory.getBean("userAction");
    	System.out.println(ua);
    	System.out.println(ua.execute());
    	
    	ua = (UserAction) factory.getBean("userAction");
    	System.out.println(ua);
    	System.out.println(ua.execute());
    	
    	ua = (UserAction) factory.getBean("userAction");
    	System.out.println(ua);
    	System.out.println(ua.execute());
    }
    

    id_name_ref(bean、local、parent)等属性的用法
    applicationContext.xml

    <!-- id命名严格,name="/aaa":还好可以加斜杠 -->
    <bean id="userAction" class="com.alyshen.spring.UserAction"
    	scope="singleton">
    	<property name="manager">
    		<!-- 
    		local="":本地的bean
    		bean="":注入的bean
    		parent="":父文件的bean
    		-->
    		<ref bean="manager" />
    	</property>
    </bean>
    

    MainClass.java

    	/**
    	 * BeanFactory factory = new
    	 * ClassPathXmlApplicationContext("applicationContext02.xml");
    	 * 
    	 * 将factory作为父工厂(已不使用)
    	 * BeanFactory fay = new XmlBeanFactory( newClassPathResource(
    	 * "applicationContext.xml"), factory );
    	 */
    

    set方法注入集合属性

    UserAction.java

    public class UserAction {
    
        public List list = null;
        public Set set = null;
        public Map map = null;
        public Properties props = null;
    
        public void setList(List list) {
            this.list = list;
        }
    
        public void setSet(Set set) {
            this.set = set;
        }
    
        public void setMap(Map map) {
            this.map = map;
        }
    
        public void setProps(Properties props) {
            this.props = props;
        }
    }
    

    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:p="http://www.springframework.org/schema/p"
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
    http://www.springframework.org/schema/beans/spring-beans-3.1.xsd">
        <!-- 
        id命名严格,name="/aaa":还好可以加斜杠 
        -->	
        <bean id="userAction" class="com.alyshen.spring.UserAction"
            scope="singleton">
    
            <property name="list">
                <list>
                    <value>zhaoliou</value>
                    <ref local="cur" />
                </list>
            </property>
    
            <property name="set">
                <set>
                    <value>dfdsf</value>
                    <value>155.54</value>
                    <value>1115</value>
                    <value type="java.lang.String">true</value>
                </set>
            </property>
    
            <property name="map">
                <map>
                    <entry key="u1">
                        <value>user1</value>
                    </entry>
                    <entry key="u2">
                        <value>user2</value>
                    </entry>
                </map>
            </property>
    
            <property name="props">
                <props>
                    <prop key="driverClass">jdbc.mysql.Driver</prop>
                    <prop key="username">root</prop>
                    <prop key="password">654321</prop>
                    <prop key="url">jdbc:mysql://localhost:3306/mydb</prop>
                </props>
            </property>
        </bean>
    
        <bean id="cur" class="java.util.Date" />
    </beans>
    
    1. MainClass.java
    public static void main(String[] args) {
    
    	BeanFactory factory = new ClassPathXmlApplicationContext(
    			"applicationContext.xml");
    	UserAction userAction = (UserAction) factory.getBean("userAction");
    
    	System.out.println("---------------list------------");
    
    	for (Object o : userAction.list) {
    		System.out.println(o);
    	}
    
    	System.out.println("---------------set------------");
    
    	for (Object o : userAction.set) {
    		System.out.println(o);
    	}
    
    	System.out.println("----------------map-----------");
    
    	for (Iterator iter = userAction.map.entrySet().iterator(); iter
    			.hasNext();) {
    		System.out.println(iter.next());
    	}
    
    	for (Object key : userAction.map.keySet()) {
    		System.out.println(key + ":" + userAction.map.get(key));
    	}
    
    	System.out.println("--------------props-------------");
    
    	Properties prop = userAction.props;
    
    	System.out.println(prop.get("driverClass"));
    	System.out.println(prop.get("username"));
    	System.out.println(prop.get("password"));
    	System.out.println(prop.get("url"));
    }
    

    构造注入及注意事项

    1. A.java
    public class A {
        private int id;
        private String username;
        private String password;
        private char sex;
        private Date birthday;
    
        @Override
        public String toString() {
            return "A [id=" + id + ", username=" + username + ", password="
                    + password + ", sex=" + sex + ", birthday=" + birthday + "]";
        }
    
        public A(int id, String username, String password, char sex, Date birthday) {
            super();
            this.id = id;
            this.username = username;
            this.password = password;
            this.sex = sex;
            this.birthday = birthday;
        }
        //各种set、get方法
        ……
    }
    
    1. 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:p="http://www.springframework.org/schema/p"
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
    http://www.springframework.org/schema/beans/spring-beans-3.1.xsd">
    
        <bean id="a" class="com.alyshen.spring.A">
            <!-- 
            构造方法注入属性,没有设置name属性时,属性要和构造方法的设置属性顺序一致,
            不一致的话可以使用index 
            -->
            <constructor-arg index="4" ref="cur" />
            <constructor-arg value="1" />
            <constructor-arg value="zhaoliou" />
            <constructor-arg value="1111" />
            <constructor-arg value="男" />
        </bean>
        <bean id="cur" class="java.util.Date" />
    </beans>
    
    1. MainClass.java
    public static void main(String[] args) {
    	BeanFactory factory = new ClassPathXmlApplicationContext("applicationContext.xml");
    
    	A a = (A) factory.getBean("a");
    	System.out.println(a.toString());
    }
    
    1. 注意事项

    a) A.java

    public class A {
    
        private B b;
    
        public void setB(B b) {
            this.b = b;
        }
    
        /**
         * 参数构造器
         */
        public A(B b) {
            super();
            this.b = b;
        }
    
        /**
         * 默认构造器
         */
        public A() {
            super();
        }
    }
    

    b) B.java

    public class B {
    
        private A a;
    
        public void setA(A a) {
            this.a = a;
        }
    
        public B(A a) {
            super();
            this.a = a;
        }
    
        public B() {
            super();
        }
    }
    

    c) 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:p="http://www.springframework.org/schema/p"
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
    http://www.springframework.org/schema/beans/spring-beans-3.1.xsd">
    
        <bean id="a" class="com.alyshen.spring.A">
            <!-- 
            不可以互相都使用构造器注入对方
            <constructor-arg ref="b" /> 
            -->
            <property name="b" ref="b" />
        </bean>
    
        <bean id="b" class="com.alyshen.spring.B">
            <!--
            <constructor-arg ref="a" /> 
            -->
            <property name="a" ref="a" />
        </bean>
    </beans>
    

    自动注入及注意事项

    1. UserManager.java
    public class UserManager {
    
    public void addUser() {
    
    	System.out.println("添加用户!");
    }
    }
    
    1. UserAction.java
    public class UserAction {
    
        private UserManager manager = null;
    
        /**
         * 参数构造器注入
         */
        public UserAction(UserManager manager) {
            super();
            this.manager = manager;
        }
    
        /**
         * set方法注入
         */
        public void setManager(UserManager manager) {
            System.out.println("调用manager的set方法注入!");
            this.manager = manager;
        }
    
        public String execute() {
            System.out.println(manager);
            manager.addUser();
            return "success";
        }
    }
    
    1. 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:p="http://www.springframework.org/schema/p"
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
    		http://www.springframework.org/schema/beans/spring-beans-3.1.xsd"
    default-autowire="byName"><!-- 统一注入方式 ,其他地方就近原则 -->
        <!-- 
        autowire="byType":按类型自动注入 ,有相同类型会抛异常 
        autowire="byName":按名称注入 
        autowire="constructor":构造注入,使用参数构造器在创建实例时将目标属性注入, 
        有两个以上相同类型的对象时,如果没有id跟属性名相同的会抛异常 ,有则使用相同的 
        -->
        <bean id="userAction" class="com.alyshen.spring.UserAction"
            scope="singleton" autowire="constructor" />
    
        <bean id="userManager" class="com.alyshen.spring.UserManager"
            scope="prototype"/>
    
        <bean id="manager" class="com.alyshen.spring.UserManager" scope="prototype"/>
    </beans>
    
    1. MainClass.java
    public static void main(String[] args) {
    
    	BeanFactory factory = new ClassPathXmlApplicationContext("applicationContext.xml");
    
    	UserAction ua = (UserAction) factory.getBean("userAction");
    	System.out.println(ua);
    	System.out.println(ua.execute());
    }
    

    通过注解注入

    1. 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:aop="http://www.springframework.org/schema/aop"
    xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="
       http://www.springframework.org/schema/beans 
       http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
       http://www.springframework.org/schema/tx 
       http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context-3.0.xsd
       http://www.springframework.org/schema/aop
       http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">
      
        <!-- 
        启用注解注入 
        -->
        <context:annotation-config />
    
        <bean id="userAction" class="com.alyshen.spring.UserAction"
            scope="singleton" />
    
        <bean id="userManager" class="com.alyshen.spring.UserManager" scope="prototype"/>
    </beans>
    
    1. UserAction.java
    public class UserAction {
    
        @Resource
        private UserManager manager = null;
        //Set方法都省了
        //	@Resource
        //	public void setManager(UserManager manager) {
        //		System.out.println("调用manager的set方法注入!");
        //		this.manager = manager;
        //	}
    
        public String execute() {
            System.out.println(manager);
            this.manager.addUser();
            return "success";
        }
    }
    

    Spring自动扫描组件

    1. 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:aop="http://www.springframework.org/schema/aop"
    xmlns:tx="http://www.springframework.org/schema/tx" 
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="
       http://www.springframework.org/schema/beans 
       http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
       http://www.springframework.org/schema/tx 
       http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context-3.0.xsd
       http://www.springframework.org/schema/aop
       http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">
        <!-- 
        启用注解注入 
        -->
        <context:annotation-config />
    
        <!-- 
        启用组件自动扫描 
        -->
        <context:component-scan base-package="com.alyshen.spring" />
    </beans>
    
    1. UserManager.java
    @Repository("uManager")
    public class UserManager {
    
        public void addUser() {
    
            System.out.println("用户管理执行添加User对象的操作!");
    
        }
    }
    
    1. UserService.java
    @Service("uService")
    public class UserService {
    
        @Resource(name = "uManager")
        private UserManager manager;
    
        public void service() {
            System.out.println("调用Service");
            manager.addUser();
        }
    }
    
    1. UserAction.java
    @Controller("uAction")
    //@Scope("prototype") //多例
    public class UserAction {
    
        @Resource(name = "uService")
        private UserService service;
    
        public String execute() {
            System.out.println("调用Action");
            service.service();
            return "success";
        }
    }
    
    1. MainClass.java
    public static void main(String[] args) {
    
    	BeanFactory factory = new ClassPathXmlApplicationContext(
    			"applicationContext.xml");
    
    	// UserAction ua = (UserAction) factory.getBean("userAction");
    
    	UserAction ua = (UserAction) factory.getBean("uAction");
    	System.out.println(ua);
    
    	ua = (UserAction) factory.getBean("uAction");
    	System.out.println(ua);
    
    	ua = (UserAction) factory.getBean("uAction");
    	System.out.println(ua);
    
    	System.out.println(ua.execute());
    }
    

    关注点分离和静态代理

    1. 关注点分离
    Me.java
    @Component
    public class Me {
    
        @Resource
        private Servant servant;
    
        public void dowork() {
    
            makeBeds();// 关注点
            dress();// 关注点
            haveAMeal();// 关注点
    
            System.out.println("我工作……");// 真正的业务
    
            haveAMeal();// 关注点
            makeBeds();// 关注点
            undress();// 关注点
    
        }
    
        // 使用面向过程编程
        private void makeBeds() {
        System.out.println("叠被子");
        }
    
        private void dress() {
        System.out.println("穿衣服");
        }
    
        private void haveAMeal() {
        System.out.println("吃饭");
        }
    
        private void undress() {
        System.out.println("脱衣服");
        }
    }
    
    1. 静态代理

    a) MeInterface.java

    public interface MeInterface {
    
        public abstract void dowork();
    }
    

    b) Me.java

    @Component("me")
    public class Me implements MeInterface {
        @Override
        public void dowork() {
    
            System.out.println("我工作……");// 真正的业务
        }
    }
    

    c) Servant.java

    @Component("ser")
    public class Servant {
        public void work1() {
            this.makeBeds();
            this.dress();
            this.haveAMeal();
        }
    
        public void work2() {
            this.haveAMeal();
            this.puChuang();
            this.undress();
        }
    
        public void makeBeds() {
            System.out.println("叠被子");
        }
    
        public void dress() {
            System.out.println("穿衣服");
        }
    
        public void haveAMeal() {
            System.out.println("吃饭");
        }
    
        public void undress() {
            System.out.println("脱衣服");
        }
    
        public void puChuang() {
            System.out.println("铺床");
        }
    }
    

    d) MyProxy.java

    @Component
    public class MyProxy implements MeInterface {
    
        @Resource(name = "me")
        private Me target;// 真正的目标对象,我们这个代理服务的对象
    
        @Resource(name="ser")
        private Servant servant;
    
        @Override
        public void dowork() {
    
            servant.work1();
    
            target.dowork();
    
            servant.work2();
        }
    }
    

    e) 使用代理

    @Test
    public void test() {
    
    	BeanFactory factory = new ClassPathXmlApplicationContext(
    			"applicationContext.xml");
    	
    	MeInterface me = (MeInterface) factory.getBean(MyProxy.class);
    	//代理将我的关注点做好再让我去工作……
    	me.dowork();
    }
    

    动态代理和横切关注点分离

    1. DynamicProxyFactory.java
    public class DynamicProxyFactory implements InvocationHandler {
    
        private DynamicProxyFactory() {
        }
    
        // 自己new的没法注入,通过创建代理的newInstance方法注入
        private Servant servant;
        private Object target;
    
        /**
         * 创建代理的静态方法
         */
        public static Object newInstance(Object target, Servant servant) {
            DynamicProxyFactory dp = new DynamicProxyFactory();
            dp.servant = servant;
            dp.target = target;
            return Proxy.newProxyInstance(target.getClass().getClassLoader(),
                    target.getClass().getInterfaces(), dp);
        }
    
        @Override
        public Object invoke(Object proxy, Method method, Object[] args)
                throws Throwable {
    
            servant.work1();
    
            Object o = // 调用动态代理类代理的目标对象上的方法(真正要调用的业务方法)
            method.invoke(target, args);
    
            servant.work2();
            return o;
        }
    }
    
    1. 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:aop="http://www.springframework.org/schema/aop"
    xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="
       http://www.springframework.org/schema/beans 
       http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
       http://www.springframework.org/schema/tx 
       http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context-3.0.xsd
       http://www.springframework.org/schema/aop
       http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">
       
        <!-- 启用注解注入 -->
        <context:annotation-config />
    
        <!-- 启用组件扫描 -->
        <context:component-scan base-package="com.ashmit.spring" />
    
        <bean id="my" class="com.ashmit.spring.DynamicProxyFactory"
            factory-method="newInstance">
            <constructor-arg ref="me" /> 
            <constructor-arg ref="ser" /> 
        </bean>
            <bean id="h" class="com.ashmit.spring.DynamicProxyFactory"
            factory-method="newInstance">
            <constructor-arg ref="he" /> 
            <constructor-arg ref="ser" /> 
        </bean>
    </beans>
    
    1. 使用动态代理
    @Test
    public void test() {
    	BeanFactory factory = new ClassPathXmlApplicationContext(
    			"applicationContext.xml");
    	
    	MeInterface me = (MeInterface) factory.getBean("my");
    	//代理将我的关注点做好再让我去工作……
    	me.dowork();
    	
    	System.out.println("--------------------");
    	HeInterface he = (HeInterface) factory.getBean("h");
    	he.hedowork();
    }
    

    利用Spring的AspectJ创建动态代理分离横切关注点

    1. 用到的包
    	aspectjrt.jar	Spring的依赖包
    	aspectjweaver.jar	Spring的依赖包
    	aopalliance.jar	aop
    	spring-aop-3.2.0.M1.jar	aop支持类
    
    1. 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:aop="http://www.springframework.org/schema/aop"
    xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="
       http://www.springframework.org/schema/beans 
       http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
       http://www.springframework.org/schema/tx 
       http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context-3.0.xsd
       http://www.springframework.org/schema/aop
       http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">
    
        <!-- 启用注解注入 -->
        <context:annotation-config />
    
        <!-- 启用组件扫描 -->
        <context:component-scan base-package="com.ashmit.spring" />
    
        <!-- 启用asppectj -->
        <aop:aspectj-autoproxy />
    </beans>
    
    1. AspClass.java
    /**
    * 切面类
    */
    @Aspect
    @Component
    public class AspClass {
    
        @Resource(name = "ser")
        private Servant servant;
    
        @Before("execution(* com.ashmit.spring.MeInterface.*(..))||execution(* com.ashmit.spring.HeInterface.*(..))")
        void before() {
            servant.work1();
        }
    
        @After("execution(* com.ashmit.spring.MeInterface.*(..))||execution(* com.ashmit.spring.HeInterface.*(..))")
        void after() {
            servant.work2();
        }
    }
    
    1. 使用Spring的AspectJ创建的动态代理
    @Test
    public void test() {
    	BeanFactory factory = new ClassPathXmlApplicationContext(
    			"applicationContext.xml");
    	
    	MeInterface me = (MeInterface) factory.getBean("me");
    	//代理将我的关注点做好再让我去工作……
    	me.dowork();
    	
    	System.out.println("--------------------");
    	HeInterface he = (HeInterface) factory.getBean("he");
    	he.hedowork();
    }
    
    1. 可以不使用切面类AspClass

    a) Servant01

    @Aspect
    @Component
    public class Servant01 implements Ordered {
    
        @Before("execution(* com.ashmit.spring.MeInterface.*(..))||execution(* com.ashmit.spring.HeInterface.*(..))")
        public void makeBeds() {
            System.out.println("叠被子");
        }
    
        @Override
        public int getOrder() {
            return 0;
        }
    }
    

    b) Servant02

    @Aspect
    @Component
    public class Servant02 implements Ordered{
    
        @Before("execution(* com.ashmit.spring.MeInterface.*(..))||execution(* com.ashmit.spring.HeInterface.*(..))")
        public void dress() {
            System.out.println("穿衣服");
        }
    
        @Override
        public int getOrder() {
            // TODO Auto-generated method stub
            return 1;
        }
    }
    

    c) Servant03

    @Aspect
    @Component
    public class Servant03 implements Ordered {
    
        @Before("execution(* com.ashmit.spring.MeInterface.*(..))||execution(* com.ashmit.spring.HeInterface.*(..))")
        public void haveAMeal() {
            System.out.println("吃饭");
        }
    
        @After("execution(* com.ashmit.spring.MeInterface.*(..))||execution(* com.ashmit.spring.HeInterface.*(..))")
        public void haveAMeal2() {
            System.out.println("吃饭");
        }
    
        @Override
        public int getOrder() {
            // TODO Auto-generated method stub
            return 2;
        }
    }
    

    d) Servant04

    @Aspect
    @Component
    public class Servant04 implements Ordered{
    
        @After("execution(* com.ashmit.spring.MeInterface.*(..))||execution(* com.ashmit.spring.HeInterface.*(..))")
        public void puChuang() {
            System.out.println("铺床");
        }
    
        @Override
        public int getOrder() {
            // TODO Auto-generated method stub
            return 1;
        }
    }
    

    e) Servant05

    @Aspect
    @Component
    public class Servant05 implements Ordered{
    
        @After("execution(* com.ashmit.spring.MeInterface.*(..))||execution(* com.ashmit.spring.HeInterface.*(..))")
        public void undress() {
            System.out.println("脱衣服");
        }
    
        @Override
        public int getOrder() {
            // TODO Auto-generated method stub
            return 0;
        }
    }
    
    1. Around、AfterThrowing等其它Advice
      a) Me.java
    @Component("me")
    public class Me implements MeInterface {
    
        @Override
        public void dowork() {
            if (true)
                throw new RuntimeException("RuntimeException……");
            System.out.println("我工作……");// 真正的业务
        }
    }
    

    b) AspClass.java

    /**
    * 切面类
    */
    @Aspect
    @Component
    public class AspClass {
    
        @Resource(name = "ser")
        private Servant servant;
    
        /**
         * @param 执行方法的东西
         * @return 返回方法的返回值
         */
            //	@Around("execution(* com.ashmit.spring.MeInterface.*(..))||execution(* com.ashmit.spring.HeInterface.*(..))")
            //	public Object test(ProceedingJoinPoint proceeding) {
            //		Object o = null;
            //		try {
            //			servant.work1();
            //			// proceeding.proceed(proceeding.getArgs());
            //			o = proceeding.proceed();
            //			
            //			servant.work2();
            //		} catch (Throwable e) {
            //			// TODO Auto-generated catch block
            //			e.printStackTrace();
            //		}
            //		return o;
            //	}
    
    
        @Before("execution(* com.ashmit.spring.MeInterface.*(..))||execution(* com.ashmit.spring.HeInterface.*(..))")
        void before() {
            System.out.println("开始代理……");
            servant.work1();
        }
        @After("execution(* com.ashmit.spring.MeInterface.*(..))||execution(* com.ashmit.spring.HeInterface.*(..))")
        void after() {
            servant.work2();
            System.out.println("结束代理……");
        }
        /**
         * 返回时执行(最后执行)
         */
        @AfterReturning("execution(* com.ashmit.spring.MeInterface.*(..))||execution(* com.ashmit.spring.HeInterface.*(..))")
        void test2() {
            System.out.println("返回……");
        }
    
        /**
         * 抛异常 注意:不能跟定义了@Around的方法连着用,否则不执行
         */
        @AfterThrowing("execution(* com.ashmit.spring.MeInterface.*(..))||execution(* com.ashmit.spring.HeInterface.*(..))")
        void test3() {
            System.out.println("抛异常……");
        }
    }
    

    Spring配置文件中配置切面

    1. AspClass.java
    /**
    * 切面类
    */
    @Component("aspclass")
    public class AspClass {
    
        @Resource(name = "ser")
        private Servant servant;
    
        void before() {
            servant.work1();
        }
    
        void after() {
            servant.work2();
        }
    }
    
    1. 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:aop="http://www.springframework.org/schema/aop"
    xmlns:tx="http://www.springframework.org/schema/tx" 
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="
       http://www.springframework.org/schema/beans 
       http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
       http://www.springframework.org/schema/tx 
       http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context-3.0.xsd
       http://www.springframework.org/schema/aop
       http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">
    
        <!-- 启用注解注入 -->
        <context:annotation-config />
    
        <!-- 启用组件扫描 -->
        <context:component-scan base-package="com.ashmit.spring" />
    
        <!-- 启用asppectj 
        <aop:aspectj-autoproxy /> 
        -->
    
        <aop:config>
            <!-- 切入点 -->
            <aop:pointcut
                expression="execution(* com.ashmit.spring.MeInterface.*(..))
        ||execution(* com.ashmit.spring.HeInterface.*(..))"
                id="mypc" />
    
            <!-- 通知 -->
            <aop:aspect ref="aspclass">
                <aop:before method="before" pointcut-ref="mypc" />
            </aop:aspect>
            <aop:aspect ref="aspclass">
                <aop:after method="after" pointcut-ref="mypc" />
            </aop:aspect>
    
        </aop:config>
    </beans>
    

    Spring AOP声明式事务

    1. 用到的包
    	commons-dbcp.jar	
    	commons-pool.jar	
    	spring-jdbc-3.2.0.M1.jar	以上dataSource需要
    	spring-orm-3.2.0.M1.jar	sessionFactory需要
    	spring-aop-3.2.0.M1.jar	aop支持类
    	spring-tx-3.2.0.M1.jar	事物通知
    
    1. 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:aop="http://www.springframework.org/schema/aop"
    xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="
       http://www.springframework.org/schema/beans 
       http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
       http://www.springframework.org/schema/tx 
       http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context-3.0.xsd
       http://www.springframework.org/schema/aop
       http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">
    
        <!-- 启用注解注入 -->
        <context:annotation-config />
    
        <!-- 启用组件扫描 -->
        <context:component-scan base-package="com.ashmit" />
    
        <!-- 数据源 -->
        <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
    
            destroy-method="close">
            <property name="driverClassName" value="com.mysql.jdbc.Driver" />
            <property name="url"
                value="jdbc:mysql://127.0.0.1:3306/ssh?createDatabaseIfNotExist=true" />
            <property name="username" value="root" />
            <property name="password" value="654321" />
        </bean>
    
        <!-- Spring的sessionFactory -->
        <bean id="sessionFactory"
            class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
            <property name="dataSource" ref="dataSource" />
            <property name="annotatedClasses">
                <list>
                    <value>com.ashmit.entity.User</value>
                    <value>com.ashmit.entity.Group</value>
                </list>
            </property>
            <property name="hibernateProperties">
                <value>
                    hibernate.dialect=org.hibernate.dialect.MySQL5Dialect
                    hibernate.show_sql=true
                    hbm2ddl.auto=update
                    javax.persistence.validation.mode=none
                    hibernate.cache.use_second_level_cache=true
                    hibernate.cache.use_query_cache=true
        hibernate.cache.region.factory_class=org.hibernate.cache.ehcache.EhCacheRegionFactory
                </value>
            </property>
        </bean>
    
        <!-- 事物管理器 -->
        <bean id="txManager"
            class="org.springframework.orm.hibernate4.HibernateTransactionManager">
            <property name="sessionFactory" ref="sessionFactory" />
        </bean>
    
        <!-- 事物通知 -->
        <tx:advice id="txAdvice" transaction-manager="txManager">
            <!-- the transactional semantics... -->
            <tx:attributes>
                <!-- all method starting with 'get' are read-only -->
                <tx:method name="get*" read-only="true" />
                <!-- other methods use the default transaction settings (see below) -->
                <tx:method name="*" />
            </tx:attributes>
        </tx:advice>
    
        <!-- 事物管理切面 -->
        <aop:config>
            <aop:pointcut id="fooServiceOperation"
                expression="execution(* com.ashmit.service.*.*(..))" />
            <aop:advisor advice-ref="txAdvice" pointcut-ref="fooServiceOperation" />
        </aop:config>
    </beans>
    
    1. 事务传播特性
    <!-- 事务通知 -->
    <tx:advice id="txAdvice" transaction-manager="txManager">
    	<!-- the transactional semantics... -->
    	<tx:attributes>
    		<!-- all method starting with 'get' are read-only -->
    		<!-- 
    		read-only="true":相当于:	this.getSession().setFlushMode(FlushMode.MANUAL);
    			MANUAL:只能执行只读事务,不刷新
    			COMMIT:提交时发出查询
    			AUTO:默认,如果有增删改,会判断你在缓存里查询的是不是脏数据,是:不让刷新
    			ALWAYS:与AUTO不同的是:不判断,直接刷新,可能会读取到脏数据
    		 -->
    		<tx:method name="find*" read-only="true" />
    		
    		<!-- other methods use the default transaction settings (see below) -->
    		<!-- 
    		isolation:隔离级别
    		propagation:事物的传播特性
    			REQUIRED:默认,使用同一个事务,没有会创建
    			REQUIRES_NEW:开启新事务
    			NEVER:永远不在事务里执行
    			NESTED:嵌套事务,设置了事务保存点,提交回滚不影响其他事务,
    				对Hibernate不起作用,只对数据源(dataSource)作用
    			NOT_SUPPORTED:不在事务里执行,如果已开启事物,这个事务会挂起
    			SUPPORTS:已开启事务就使用,没有开启事务就在没有事务环境下执行
    			MANDATORY:必须在已开启事务的环境下运行,没有开启就抛异常
    		-->
    		<tx:method name="*" propagation="REQUIRED"/>
    	</tx:attributes>
    </tx:advice>
    

    Spring与Struts框架的集成

    1. 用到的包
    struts2-spring-plugin-2.3.4.jar	在Struts文件中
    spring-web-3.2.0.M1.jar	在Spring文件中
    
    1. UserAction.java
    @Controller("userAction")
    public class UserAction implements ModelDriven {
    
        private User user = null;
    
        @Resource(name = "groupService")
        private GroupService groupService = null;
    
        @Resource(name = "userService")
        private UserService userService = null;
    
        //各种方法
        ……
    }
    
    1. web.xml
    <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
    id="WebApp_ID" version="3.0">
    
        <!-- 创建sessionFactory并将其置入ServletContext当中的监听器 -->
        <listener>
            <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
        </listener>
    
        <!-- 指定Spring工厂配置文件所在路径的全局参数,ContextLoaderListener专用 -->
        <context-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>/WEB-INF/applicationContext-*.xml,classpath*:applicationContext-*.xml</param-value>
        </context-param>
    
        ……
    </web-app>
    

    BaseDao模式

    1. BaseDao.java
    public class BaseDao {
    
        @Resource(name = "sessionFactory")
        private SessionFactory sessionFactory = null;
    
        protected Session getSession() {
            return this.sessionFactory.getCurrentSession();
        }
    }
    

    OpenSessionInView模式

    应对懒加载策略

    <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
    id="WebApp_ID" version="3.0">
    
        <!-- 创建sessionFactory并将其置入ServletContext当中的监听器 -->
        <listener>
            <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
        </listener>
    
        <!-- 指定Spring工厂配置文件所在路径的全局参数,ContextLoaderListener专用 -->
        <context-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>/WEB-INF/applicationContext-*.xml,classpath*:applicationContext-*.xml</param-value>
        </context-param>
    
        <!-- 启用尽早打开尽可能晚关闭session的filter -->
        <filter>
            <filter-name>OpenSessionInViewFilter</filter-name>
            <filter-class>org.springframework.orm.hibernate4.support.OpenSessionInViewFilter</filter-class>
        </filter>
        <filter-mapping>
            <filter-name>OpenSessionInViewFilter</filter-name>
            <url-pattern>/*</url-pattern>
        </filter-mapping>
    
        ……
    </web-app>
    
  • 相关阅读:
    HanTTS简单文档
    一张包含所有颜色的图片
    shiro整合SpringMVC基于xml
    设计模式-享元模式
    关于volatile关键字实现的个人理解
    重量级锁
    轻量级锁
    偏向锁
    Seata概念的总结
    苹果手机怎么把资源库的APP放到桌面
  • 原文地址:https://www.cnblogs.com/yhongyin/p/12004406.html
Copyright © 2020-2023  润新知